gremlingraph-databases

How to use previous step values to filter the next step [GREMLIN]


I am fetching my vertices recursively using repeat. now i want to be able to use the values of a previous step inside repeat and compare it as a reference to make my search for vertices more accurate.

below is a portion of my graph database, the marked vertices are the vertices that i want to fetch. enter image description here

this is my fetch query:

g
.V()
.has('name', 'f4')
.repeat(
    inE()
    .choose(
        label()
    )
    .option(
        'uses',
        outV()
    )
    .option(
        'has',
        choose(outV().label())
        .option(
            'cd',
            outV()
            .as('vv')
            .in('has')
            .inE('uses')
            .where(has('value', select('vv').values('name')))
            .outV()
        )
    )
)
.until(inE().count().is(0))
.emit(
    hasLabel('formula')
)

as you can see from my query there is a step modulator that is tagged vv. i want to be able to get the vertex in vv and compare it inside where step.

the problem with my query above is it is only able to get f1 and f6 vertices. i also need to fetch the formula vertex with name: f7

please use the query below to seed your graphdatabase:

g
.addV('product')
.property('name', 'product1')
.as('p')
.addE('has')
.to(
    addV('cd')
    .property('name', 'cd1')
    .as('cd1')
    .addE('has')
    .to(
        addV('formula')
        .property('name', 'f4')
        .as('f4')
        .addE('has')
        .from(
            addV('health_score').property('name', 'h1')
            .as('h1')
            .addE('uses')
            .from(addV('formula').property('name', 'f5'))
            .select('h1')
        )
        .select('f4')   
    )
    .select('cd1')
)
.select('p')
.addE('has')
.to(
    addV('cd')
    .property('name', 'cd2')
)
.select('p')
.addE('has')
.to(
    addV('cd')
    .property('name', 'cd3')
)
.select('p')
.addE('uses')
.property('value', 'cd1')
.from(
    addV('formula')
    .property('name', 'f1')
    .as('f1')
    .addE('uses')
    .from(
        addV('formula')
        .property('name', 'f6')
    )
    .select('f1')
    .addE('has')
    .from(
        addV('cd')
        .property('name', 'cd4')
        .as('cd4')
        .addE('has')
        .from(
            addV('product')
            .property('name', 'product2')
            .as('product2')
            .addE('uses')
            .property('value', 'cd4')
            .from(
                addV('formula')
                .property('name', 'f7')
            )
            .select('product2')
        )
        .select('cd4')
    )
    .select('f1')
)
.select('p')
.addE('uses')
.from(addV('formula')
.property('name', 'f2'))
.select('p')
.addE('uses')
.from(addV('formula')
.property('name', 'f3'))

Solution

  • I believe the pattern you're looking for is where()-by(): https://www.kelvinlawrence.net/book/PracticalGremlin.html#whereby

    g
    .V()
    .has('name', 'f4')
    .repeat(
        inE()
        .choose(
            label()
        )
        .option(
            'uses',
            outV()
        )
        .option(
            'has',
            choose(outV().label())
            .option(
                'cd',
                outV()
                .as('vv')
                .in('has')
                .inE('uses')
                .where(eq('vv')).by('value').by('name')
                .outV()
            )
        )
    )
    .until(inE().count().is(0))
    .emit(
        hasLabel('formula')
    )
    

    This returns:

    [ {"id":4341, "label":"formula"}, {"id":4344, "label":"formula"} ]
    

    With using: .where(eq('vv')).by('value').by('name') the two by modulators define what you are comparing. The first by() defines what you are passing into the where() and the second by() modulates what are you are referencing in the where() (so vv in this case).