0

Let's assume we have a graph of persons, with properties

  • name (String)
  • age (int)

... and friend edges in between some of them. Let's further assume we have a complex gremlin query which eventually produces person vertices.

Now, for each of the resulting persons, we want to find the three oldest friends in a subquery.

This is the rough query structure:

g.traversal.V()
    // complex filtering and navigation here, produces person vertices
    .flatMap(
        __.out(friend)
        .order().by("age", desc)
        .limit(3)
    )
    // complex query continues with the three oldest friends per input vertex here

The problem with this query is that the order().by(...) step is global. I get three persons in total for all person vertices which enter the flatMap(...).

What I would like to receive is (up to) three persons per vertex entering the flatMap(...) step.

How would you do that in gremlin? I've read that there is "local" scoping of sorts, but I was unable to make it work.

Martin Häusler
  • 6,544
  • 8
  • 39
  • 66

1 Answers1

0

I would expect your traversal to work as you would wish it to. See my examples with TinkerGraph and the "modern" toy graph:

gremlin> g.V().hasLabel('person').flatMap(out().order().by(id))
==>v[2]
==>v[3]
==>v[4]
==>v[3]
==>v[5]
==>v[3]
gremlin> g.V().hasLabel('person').flatMap(out().order().by(id).limit(1))
==>v[2]
==>v[3]
==>v[3]
gremlin> g.V().hasLabel('person').flatMap(out().order().by(id).limit(2))
==>v[2]
==>v[3]
==>v[3]
==>v[5]
==>v[3]

Or perhaps easier to see in action with just map():

gremlin> g.V().hasLabel('person').map(out().order().by(id).fold())
==>[v[2],v[3],v[4]]
==>[]
==>[v[3],v[5]]
==>[v[3]]
gremlin> g.V().hasLabel('person').map(out().order().by(id).limit(1).fold())
==>[v[2]]
==>[]
==>[v[3]]
==>[v[3]]
gremlin> g.V().hasLabel('person').map(out().order().by(id).limit(2).fold())
==>[v[2],v[3]]
==>[]
==>[v[3],v[5]]
==>[v[3]]

Perhaps there is something in your data that you are not expecting? If the problem persists maybe you could debug with map() as I showed above and see what's being returned before the lists are flattened? If all else fails, please update your question with a script that provides some sample data and a Gremlin Console session demonstrating the failure with that data.

stephen mallette
  • 45,298
  • 5
  • 67
  • 135
  • The problem isn't flat map, it's the `order().by(...)`. I want the 3 *oldest* friends of each person. The order by waits for all other traversers (i.e. it acts as a globally blocking step), and the output of my flat map is always at most 3 persons. I would like to have the 3 oldest persons per vertex that arrives as input to `flatMap()`. – Martin Häusler Jan 14 '19 at 13:46
  • I understand the problem, but I was trying to demonstrate that I can't recreate it. I updated my answer to include `order()` and I can see no such restriction where I globally only get 3 results total. am i still missing something? can you demonstrate the problem in a console session as I suggested? what graph database are you using...perhaps there is a bug in their implementation? – stephen mallette Jan 14 '19 at 14:01
  • Hm... you're right, I just tried it myself on TinkerGraph. Maybe I was jumping to conclusions too quickly. The gremlin query surrounding this `flatMap(...)` was quite complex, so maybe I made a mistake somewhere else. Thanks, I appreciate the effort! – Martin Häusler Jan 14 '19 at 14:29