0
votes

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.

1

1 Answers

3
votes

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")