ChristianSchmaler
ChristianSchmaler

Reputation: 1

Keeping track of already visisted vertexes in sack

I want to make use of the sack to keep track of which vertexes have already been traversed and not continuing if the traverser encounters a vertex that is already in the list. The sack could keep a list of vertexes (either the vertex itself, or the vertex id or some other unique property like name in this case).

So here condensed to the absolute minimum: there is a starting vertex with name 'TS', it's put in the sack and then two edges are traversed, checking the reached vertex is not the starting vertex again. I tried to express it like this, but the returned paths always include path starting and ending at TS.

g.withSack([]){it.clone()}
    .V()
    .has('name', 'TS')
    .sack{a,v->a+=v.id()}
    .both()
    .both()
    .where(id().not(is(within(sack()))))
    .path().by('name')

Same in this example, expressing a little bit more what I intend to do

g.withSack([]){it.clone()}
    .V()
    .has('name', 'TS')
    .sack{a,v->a+=v.id()}
    .repeat(
        both()
        .where(id().not(is(within(sack()))))
        .sack{a,v->a+=v.id()}
    )
    .times(2)
    .path().by('name')

As a side note: I know about simplePath, but this is more about keeping track of some (not all) vertexes that have been visited already - because only some vertexes will go into the sack, not all of them.

Is my query wrong or is there some erroneous reasoning and the whole idea cannot work?

Upvotes: 0

Views: 42

Answers (1)

Taylor Riggan
Taylor Riggan

Reputation: 2769

Sack isn't really meant to be used this way. You're better off using something like aggregate() or store().

Example query here where I have a graph of movie artists (actors/actresses) and corresponding movies they performed in:

(Artist)<-(movie)->(Artist)

Say I wanted to find all movies that Kevin Bacon and actors up to two hops away also performed in, where the runtime of the movie was less than 45 minutes:

g.V().hasLabel('Artist').has('name','Kevin Bacon').
    repeat( 
        in('actor','actress').
        sideEffect(where(values('runtime').is(lte(45))).aggregate('shortshows')).
        out('actor','actress').simplePath()
    ).times(2).cap('shortshows').
    select('shortshows').unfold().dedup().valueMap()

Which returns:

1   {'title': ['The Big Green'], 'year': [2014], 'runtime': [32]}
2   {'title': ['Material of the Future'], 'year': [2014], 'runtime': [41]}
3   {'title': ['California Sea Lions'], 'year': [2004], 'runtime': [45]}
4   {'title': ['Sky Island'], 'year': [2010], 'averageRating': [7.4], 'numVotes': [47], 'runtime': [27]}
5   {'title': ['To the Arctic 3D'], 'year': [2012], 'averageRating': [6.6], 'numVotes': [1006], 'runtime': [40]}
6   {'title': ['The Man Who Built Cambodia'], 'year': [2017], 'averageRating': [8.9], 'numVotes': [9], 'runtime': [35]}
7   {'title': ['Hope in Heaven'], 'year': [2005], 'averageRating': [6.7], 'numVotes': [19], 'runtime': [45]}
8   {'title': ['Herschel Hopper: New York Rabbit'], 'year': [2000], 'averageRating': [6.8], 'numVotes': [19], 'runtime': [45]}
9   {'title': ['In the Night I Remember Your Name'], 'year': [2018], 'runtime': [44]}
10  {'title': ['Stuart Davis: In Full Swing'], 'year': [2017], 'runtime': [30]}

The aggregate() allows me to collect the results as I go. The sideEffect() allows me to do this and not filter out paths in the traversal along the way. cap() ensures that all of the traversals collapse back to a single traversal before then fetching the results from the aggreagate (which will be stored in a list), unfolding the list, deduping the results, and displaying all of their properties.

You don't need all that lambda-mumbo-jumbo. ;)

Upvotes: 0

Related Questions