2

I am starting to learn graph databases and have hit a small snag with a query in the Gremlin query language for a proof of concept.

Say I have a vertex that represents a specific type of bolt and each of the properties represent a material and cost that the bolt is available in.

id: bolt-123,
label: part,
properties: [
    { steel : 0.05 },
    { aluminum : 0.02 },
    { iron : 0.03 },
    { plastic : 0.01 }
]

I would like to be able to get a list of all bolts and their cost that are made out of plastic. With my currently limited knowledge of Gremlin, I have been able to come up with the following query:

g.V().hasLabel('part').has('plastic').project('key', 'value').by('id').by('plastic')

which results in

[ { "key": "bolt-123", "value": 0.01 },
  { "key": "bolt-456", "value": 0.02 } ]

While this query makes perfect sense to me, I am hoping to flatten this out a little bit more so that I could have:

[ { "bolt-123", 0.01 },
  { "bolt-456", 0.02 } ]

Thanks for helping a Gremlin newbie out.

KyKo
  • 382
  • 4
  • 15

1 Answers1

9

If you just want the values of the Map you can append select(values) to the end of that traversal and it will drop the keys. I'll use the "modern" graph as an example:

gremlin> g.V().project('k','v').by(id).by('name').select(values)
==>[1,marko]
==>[2,vadas]
==>[3,lop]
==>[4,josh]
==>[5,ripple]
==>[6,peter]

Of course, if you don't need the Map then I wouldn't bother to project() it in the first place, just create the List of values instead:

gremlin> g.V().map(union(id(),values('name')).fold())
==>[1,marko]
==>[2,vadas]
==>[3,lop]
==>[4,josh]
==>[5,ripple]
==>[6,peter]

If you want the exact output you presented you could coerce the List to a Map with group():

gremlin> g.V().
......1>   map(union(id(),values('name')).
......2>       fold().
......3>       group().
......4>         by(limit(local,1)).
......5>         by(tail(local)))
==>[1:marko]
==>[2:vadas]
==>[3:lop]
==>[4:josh]
==>[5:ripple]
==>[6:peter]

it's basically taking each List and taking the key for the Map from the first item in the list with limit(local,1) and then taking the value from the second item in the list with tail(local).

Of course, it occurs to me now that if your "id" is truly unique then you could omit the union() and just do group():

gremlin> g.V().group().by(id()).by(values('name').unfold())
==>[1:marko,2:vadas,3:lop,4:josh,5:ripple,6:peter]

Note that I purposefully did by(values('name').unfold()) instead of by('name') because the latter would wrap the result in a List.

stephen mallette
  • 45,298
  • 5
  • 67
  • 135
  • That is certainly much closer to what I would like (and gives me more operations to look into), but I was hoping to have it in JSON format so that I could easily deserialize the results into a .NET collection without having to loop through the returned 2D array. I'll keep looking, but any thoughts? – KyKo Jan 14 '19 at 15:04
  • you can coerce the list pairs to maps with `group()` - i've updated my answer - should be just what you want now. – stephen mallette Jan 14 '19 at 15:34
  • Thank you, this certainly looks like what I would need and gives me a lot more to learn about how query operators work and chain together. I'm still learning how to query data for various access scenarios first , then build a Proof of Concept app to use those queries. – KyKo Jan 14 '19 at 16:53