I'm looking for a pattern.
I'm working on this query:
g.V().has('objid','7615388501660').as('location')
.in('enhabits').as('population')
.out('isInFaction').as('faction')
.in('isInFaction').out('isOfSpecies').as('species')
.path().by('name')
and I get this back:
"labels": [
["location"],
["population"],
["faction"],
[],
["species"]
],
"objects": [
"Plara",
"Se Bemon",
"Se",
"Se Bemon",
"Wan"
]
but there is an extra step [] that I feel is the wrong approach. It also traverses through all of the populations in that faction, not just the one I want. What I want is each record of the location, population, faction, species in a list. Or, in another way, for each population in that location, I want that population, it's faction, it's species.
You can often flatten these backtracking type of use cases by introducing a union step into the query. Something along the lines of :
g.V().has('objid','7615388501660').as('location').
in('enhabits').as('population').
local(
union(
out('isInFaction').as('faction'),
out('isOfSpecies').as('species')).
fold()).
path().
by(unfold().values('name').fold())
Related
`
g.V().hasLabel('node1') \
.as('prop1', 'prop2', 'prop3', 'prop4', 'prop5', 'prop6', 'prop7', 'node1_id_prop8', 'prop9') \
.inE().hasLabel('edge').outV().hasLabel('node2').id().as('node2_id_prop10') \
.select('prop1', 'prop2', 'prop3', 'prop4', 'prop5', 'prop6', 'prop7',
'node1_id_prop8', 'prop9', 'node2_id_prop10') \
.by('prop1').by('prop2').by('prop3').by('prop4').by('prop5') \
.by(values('prop6').fold()).by('prop7').by(T.id).by('prop9').by(T.id).toList()
Here I want to get values include both node ID's?
But I am getting
error message '{'requestId': '7abb9f32-a228-44fb-9206-8b034eb67aa5', 'status': {'message': '{"code":"InternalFailureException","requestId":"7abb9f32-a228-
44fb-9206-8b034eb67aa5","detailedMessage":"TokenTraversal support of java.lang.String does not allow selection by id"}', 'code': 500, 'attributes': {}}, 'result':
{'data': None, 'meta': {}}}'
`
I am expecting to get list of key value pair values that traverse through this node.
With Gremlin, you typically want to follow a pattern where you're touching/fetching the higher level components in the graph first, and then applying filters and serialization techniques later in the query.
In your example, you want to traverse from node1 to node2 first and gather up those higher level components (the vertices) before starting to worry about the properties. You can do that using as() or aggregate()...
A side note here: You typically want to use labels as lower cardinality concepts. Think of them as groupings, or if coming from a relational database background, you can think of them as table names. You typically would not have a vertex/node with a label of "node1". It is more common that you would have a vertex/node with an ID of "node1".
g.V().hasLabel('node1').
aggregate('v').
inE().hasLabel('edge').outV(). # this can be simplified as in('edge')
hasLabel('node2').
aggregate('v').
The values in the aggregate then form a list that you can now select and perform other operations upon. In this case, you want all of the available properties for each of those two vertices. The valueMap() step creates a map of all properties associated with a vertex. Adding true inside of the valueMap() adds the ID and label. The unfold() step here is to unroll the aggregated list and pass each vertex in the list to valueMap():
select('v').
unfold().
valueMap(true)
That would get you a list of maps for each vertex in the following fashion:
[{
<T.id: 1>: <id>,
<T.label: 4>: 'node2',
'Prop1': ['prop1']
},{
<T.id: 1>: <id>,
<T.label: 4>: 'node1',
'Prop1': ['prop1'],
'Prop2': ['prop2'],
'Prop3': ['prop3'],
'Prop4': ['prop4'],
'Prop5': ['prop5'],
...
'Propn': ['propn']
}]
I want the details of a vertex along with details of vertices that are joined to it.
I have a group vertex, incoming 'member' edges to user vertices. I want the details of the vertices.
g.V(1).as('a').in('member').valueMap().as('b').select('a','b').unfold().dedup()
==>a=v[1]
==>b={image=[images/profile/friend9.jpg], name=[Thomas Thompson], email=[me#thomasthompson.co.uk]}
==>b={image=[images/profile/friend13.jpg], name=[Laura Tostevin], email=[me#lauratostevin.co.uk]}
==>b={image=[images/profile/friend5.jpg], name=[Alan Thompson], email=[me#alanthompson.co.uk]}
==>b={image=[images/profile/friend10.jpg], name=[Laura Bourne], email=[me#laurabourne.co.uk]}
Ideally what I'd want is:
{label: 'group', id=1, name='A Group', users=[{id=2, label="user",name=".."}, ... }]}
When I tried a project, it didn't like me using 'in'
gremlin> g.V('1').project('name','users').by('name').by(in('member').select())
groovysh_parse: 1: unexpected token: in # line 1, column 83.
'name','users').by('name').by(in('member
To get your preferred output format, you have to join the group's valueMap() with the list of users. On TinkerPop's modern toy graph you would do something like this:
gremlin> g.V(3).union(valueMap(true).
by(unfold()),
project('users').
by(__.in('created').
valueMap(true).
by(unfold()).
fold())).
unfold().
group().
by(keys).
by(select(values))
==>[name:lop,id:3,lang:java,label:software,users:[[id:1,label:person,name:marko,...],...]]
Mapping this to your graph should be pretty straight-forward, it's basically just about changing labels.
Because in is a reserved keyword in Groovy you must use the verbose syntax __.in
try:
g.V('1').project('name','users').by('name').by(__.in('member').valueMap(true).fold())
I'm having trouble constructing the gremlin query to give me all of the Edge details(label, properties) and also the ID's of the Inv and OutV adjoining Vertex's (I don't need any more info from the linked Vertex's, just the ID's).
All I have is the Edge ID as a starting point.
So my Edge is as follows:
Label: "CONTAINS"
id: c6b4f3cb-f96e-cc97-dedb-e405771cb4f2
keys:
key="ekey1", value="e1"
key="ekey2", value="e2"
inV has id 50b4f3cb-f907-c31c-6284-1a3463fd72b9
outV has id 7cb4f3cb-d9a2-1398-61d7-9339be34833b
What I want is a single query that will return me something like -
"CONTAINS", "c6b4f3cb-f96e-cc97-dedb-e405771cb4f2", {ekey1=e1, ekey2=e2, ...}, "50b4f3cb-f907-c31c-6284-1a3463fd72b9", "7cb4f3cb-d9a2-1398-61d7-9339be34833b"
I can get the info in separate queries i.e.
g.E("c6b4f3cb-f96e-cc97-dedb-e405771cb4f2").bothV()
==>v[50b4f3cb-f907-c31c-6284-1a3463fd72b9]
==>v[7cb4f3cb-d9a2-1398-61d7-9339be34833b]
g.E("c6b4f3cb-f96e-cc97-dedb-e405771cb4f2").valueMap()
==>{ekey1=e1, ekey2=e2}
g.E("c6b4f3cb-f96e-cc97-dedb-e405771cb4f2").label()
==>CONTAINS
But I can't for the life of me work out how to combine these into one.
You could use project() to get what you're looking for:
g.E("c6b4f3cb-f96e-cc97-dedb-e405771cb4f2").
project('ekey1', 'inV', 'outV', 'label').
by('ekey1').
by(inV().id()).
by(outV().id()).
by(label).
I have the following traversal that shows that the selected Vertex has 14 Edges labeled "follows".
g.V().has('user','email','me#email.com').project('name','email','follow-edges').by('name').by('email').by(outE().hasLabel('follows').project('id','inV').by('id').by('inV'))
Which produces the following results:
[{
"name": "David",
"email": "me#email.com",
"follow-edges": 14}]
But when I want to project the "follows" Edge's id and inV ids, I'm only getting one result item back.
g.V().has('user','email','david#me.com').project('name','email','follow-edges').by('name').by('email').by(outE().hasLabel('follows').project('edge-id', 'inV-id').by('id').by('inV'))
Results:
[{
"name": "David",
"email": "me#email.com",
"follow-edges": {
"edge-id": "ccc06183-f4ca-410d-9c3c-9d2dfd93f5f0",
"inV-id": "f4703a07-f42d-46f9-86be-7f5440f07f12"
}}]
I was expecting to get a list of all the "follows" edge's for the selected vertex. Similiar to the answer given by Stephen Mallette at this link.
Does anyone know why this is not working?
You need to reduce the stream of objects in your anonymous traversal in by() - note my addition of fold():
g.V().has('user','email','david#me.com').
project('name','email','followedges').
by('name').
by('email').
by(outE().hasLabel('follows').
project('edge-id', 'inV-id').
by('id').
by('inV').fold())
I assume that "inV" is an actual property and you're not trying to get the "in vertex" of the edge. If you are trying to get the "in vertex" then you need by(inV().id()).
Even though Freebase was deprecated in Jun. 2015, I was impressed by Freebase's MQL. It is intuitive, concise, declarative, and easy to understand/write.
These days I'm learning about TinkerPop3 and gremlin. I think gremlin has many good features. I wonder whether I could convert Freebase MQL to TinkerPop3 gremlin.
Let's say, I have TinkerPop3 sample data "The Crew" and following MQL:
[{
"type": "person",
"name": null,
"develops": {
"type": "software",
"release_date": null, // release_date is not in the crew data.
// Just added for test
"name": null,
"sort": "-name", // descending sort
"limit": 2 // print only two software
},
"uses": {
"type": "software",
"release_date": null,
"name": null,
"sort": "name", // ascending sort
"limit": 2
}
}]
Above MQL means "find person", and for each person "print his two developed software and used software". Please keep in mind that above MQL is just an example for testing.
I've tried to convert MQL to a single gremlin. But I couldn't convert it. So I'm asking you. Is it possible? then how to convert, if impossible why? (If it is possible it would be better if a generated gremlin is efficient in terms of optimization and execution.)
If single gremlin is impossible, then is it possible assembling two or more gremlin can generate as same as MQL's output without performance loss?
Thanks in advanced.
The fastest query to solve this problem should be the following:
gremlin> g.V().hasLabel("person").as("person").
gremlin> map(out("develops").order().by("name", decr).limit(2).fold()).as("develops").select("person").
gremlin> map(out("uses").order().by("name", incr).limit(2).fold()).as("uses").
gremlin> select("person","develops","uses")
==>[person:v[1], develops:[v[11], v[10]], uses:[v[10], v[11]]]
==>[person:v[7], develops:[v[11], v[10]], uses:[v[10], v[11]]]
==>[person:v[8], develops:[v[10]], uses:[v[10], v[11]]]
==>[person:v[9], develops:[], uses:[v[10], v[11]]]
However, using the match() step, you can probably enhance the readability (although it contains the same steps):
g.V().hasLabel("person").match(
__.as("person").out("develops").order().by("name", decr).limit(2).fold().as("develops"),
__.as("person").out("uses").order().by("name", incr).limit(2).fold().as("uses")).
select("person","develops","uses")
UPDATE
Since you don't want to see me (v[9]) in the result set, you can add a simple filter condition:
g.V().hasLabel("person").as("person").
filter(outE("develops").and().outE("uses")).
map(out("develops").order().by("name", decr).limit(2).fold()).as("develops").select("person").
map(out("uses").order().by("name", incr).limit(2).fold()).as("uses").
select("person","develops","uses")