1

New at Gremlin and CosmosDB I tried to persist two vertices of type "Person". One of them has a phone number the other doesn't. (pk/pk is the PartitionKey)

g.addV('Person').property(id, '1').property('Name','Jack').property('Phone','213').property('pk', 'pk')
g.addV('Person').property(id, '2').property('Name','Peter').property('pk', 'pk')

Next I wanted to get both entries out of the database in an JSON Format with only the fields 'name' and 'phone':

g.V().hasLabel('Person').project('name','phone').By('Name').By('Phone').fold()

But when executing the query I get the following error:

Error: Project By: Next: The provided traverser of key \"phone\" maps to nothing

I would expect something like this:

[ 
  {
    "Name": "Jack",
    "Phone": "213"
  },
  {
    "Name": "Peter"
  }
]

How can I fix this? Adding an empty 'Phone' property is not an option.

1 Answers1

0

I assume your question is about project() specifically and that alternatives like elementMap() and valueMap() don't work for you for some reason in this case of having to deal with non-existent keys. With project() you provide the keys and those keys must have values at least until Gremlin 3.5.0 when null will be supported as part of the language.

For now, with project() you can account for the missing property with something like coalesce() but it means providing some kind of default value when that property key is not present:

g.V().hasLabel('Person').
  project('name','phone').
    by('Name').
    by(coalesce(values('Phone'),constant("")))

You could also filter() those keys away that hold the constant() I suppose, but your Gremlin just gets uglier from there.

I think that if I needed this specific form that you're looking for I'd probably look away from project() where the key must exist. Examples might be:

gremlin> g.V().valueMap('name','age').by(unfold())
==>[name:marko,age:29]
==>[name:vadas,age:27]
==>[name:lop]
==>[name:josh,age:32]
==>[name:ripple]
==>[name:peter,age:35]
gremlin> g.V().elementMap('name','age')
==>[id:1,label:person,name:marko,age:29]
==>[id:2,label:person,name:vadas,age:27]
==>[id:3,label:software,name:lop]
==>[id:4,label:person,name:josh,age:32]
==>[id:5,label:software,name:ripple]
==>[id:6,label:person,name:peter,age:35]
gremlin> g.V().map(properties('name','age').group().by(key).by(value()))
==>[name:marko,age:29]
==>[name:vadas,age:27]
==>[name:lop]
==>[name:josh,age:32]
==>[name:ripple]
==>[name:peter,age:35]
gremlin> g.V().valueMap('name','age').map(unfold().group().by(keys).by(select(values).unfold()))
==>[name:marko,age:29]
==>[name:vadas,age:27]
==>[name:lop]
==>[name:josh,age:32]
==>[name:ripple]
==>[name:peter,age:35]
gremlin> g.V().
......1>   project('name','age').
......2>     by('name').
......3>     by(coalesce(values('age'), constant(Integer.MIN_VALUE))).
......4>   map(unfold().
......5>       filter(select(values).is(neq(Integer.MIN_VALUE))).
......6>       fold())
==>[name=marko,age=29]
==>[name=vadas,age=27]
==>[name=lop]
==>[name=josh,age=32]
==>[name=ripple]
==>[name=peter,age=35]
stephen mallette
  • 45,298
  • 5
  • 67
  • 135
  • Thanks for the answer, but this would add an empty "Phone" property to the JSON. It should be missing or set to NULL, not have a value of "empty" – Thomas Bingel Jul 17 '20 at 16:55
  • Gremlin does not have first class support for `null` until 3.5.0: https://tinkerpop.apache.org/docs/3.5.0-SNAPSHOT/upgrade/#_use_of_null and even then most graph databases tend to not "store" `null` so it will be interesting to see how that it used in the future. updated my answer with some other options – stephen mallette Jul 17 '20 at 17:34
  • Thanks again for your help! I really appreciate it!. But 'g.V().valueMap('name','age').by(unfold())' returns the error: Gremlin op does not support by(traversal). 'g.V().elementMap('name','age')' returns the error: Unable to find any method 'elementMap' and 'g.V().map(properties('Name','Phone').group().by(key).by(value()))': returns the error: The provided traversal or property name does not exist as the key has no associated value for the element. Or an empty result when leaving the property names in lower letters... – Thomas Bingel Jul 17 '20 at 17:50
  • sorry - this tends to happen with CosmosDB a lot. What works for the current Gremlin language standard may not yet be implemented in CosmosDB. i added another attempt - it's getting uglier again though – stephen mallette Jul 17 '20 at 17:57
  • The query 'g.V().valueMap('Name','Phone').map(unfold().group().by(keys).by(select(values).unfold()))' returns: " GraphAssertException\nExceptionMessage :\r\n\tcompositeObjField != null"... and 'g.V().valueMap('name','age').map(unfold().group().by(keys).by(select(values).unfold()))' returns an empty result in CosmosDB. Can you verify it with my data? With the property 'name' and 'phone' ? – Thomas Bingel Jul 17 '20 at 18:22
  • The key casing and data will not change the outcome I'm afraid. CosmosDB for this particular case, just doesn't support the options I'm providing. my ideas for this are just getting uglier, but I added another – stephen mallette Jul 17 '20 at 18:45
  • Sorry, its not working. Phone would be a string, not a number. Maybe there is no way to do this in CosmosDB – Thomas Bingel Jul 17 '20 at 19:03
  • i mean...you could do `constant("XXX-XXX-XXXX")` or the like. i was just fitting the sample graph i keep using. – stephen mallette Jul 17 '20 at 19:37