Get array's first item as object in TinkerPop3 Gremlin query and JanusGraph

Viewed 2465

I faced this issue during a migration of gremlin queries from v2 to v3.

V2-way: inE().has(some condition).outV().map().toList()[0] will return an object. This is wrapped in transform{label: it./etc/} step.

V3-way, still WIP: inE().has(some condition).outV().fold() will return an array. This is wrapped in project(...).by(...) step.

V3 works fine, I just have to unwrap an item from the array manually. I wonder if there is a more sane approach (anyway, this feels like non-graph-friendly step).

Environment: JanusGraph, TinkerPop3+. For v2: Titan graph db and TinkerPop2+.

Update: V3 query sample

inE('edge1').
  has('cond1').outV(). // one vertex left
  project('items', 'count'). // pagination
    by(
      order().
        by('field1', decr).
          project('vertex_itself', 'vertex2', 'vertices3').
            by(identity()).
            by(outE('edge2').has('type', 'type1').limit(1).inV().fold()). // now this is empty array or single-element array, can we return element itself?
            by(inE('edge2').has('type', 'type2').outV().fold()).
          fold()).
    by(count())

Desired result shape:

[{
  items: [
    {vertex_itself: Object, vertex2: Object/null/empty, veroces3: Array},
    {}...
  ],
  cont: Number,
}]

Problem: vertex2 property is always an array, empty or single-element.
Expected: vertex2 to be object or null/empty.

Update 2: it turns out my query is not finished yet, it returns many object if there are no single element in has('cond1').outV() step, e.g. [{items, count}, {items, count}...]

2 Answers

it looks like your main issue is getting a single item from the traversal.

you can do this with next(), which will retrieve the next element in the current traversal iteration:

inE().has(some condition).outV().next()

the iteratee's structure is, i think, implementation specific. e.g. in javascript, you can access the item with the value property:

const result = await inE().has(some condition).outV().next();
const item = result.value;

I may not fully understand, but it sounds like from this:

inE().has(some condition).outV().fold()

you want to just grab the first vertex you come across. If that's right, then is there a reason to fold() at all? maybe just do:

inE().has(some condition).outV().limit(1)
Related