Multiple add if doesn't exist steps Gremlin

165 Views Asked by At

I have an injected array of values. I'm I want to add vertices if they don't exist. I use the fold and coalesce step, but it doesn't work in this instance since I'm trying to do it for multiple vertices. Since 1 vertex exists I can no longer get a null value, and the the unfold inside the coalesce step returns a value from there on. This leads to vertices that don't exist yet not to be added.

This is my current traversal:

const traversal = await g
    ?.inject([
        { twitterPostId: 'kay', like: true, retweet: false },
        { twitterPostId: 'fay', like: true, retweet: false },
        { twitterPostId: 'nay', like: true, retweet: false },
    ])
    .unfold()
    .as('a')
    .aggregate('ta')
    .V()
    .as('b')
    .where('b', p.eq('a'))
    .by(__.id())
    .by('twitterPostId')
    .fold()
    .coalesce(__.unfold(), __.addV().property(t.id, __.select('ta').unfold().select('twitterPostId')))
    .toList();

Returns:

        [Bn { id: 'kay', label: 'vertex', properties: undefined }]
1

There are 1 best solutions below

0
On

Without using coalesce you can do conditional upserts using what we often refer to as "map injection". The Gremlin does get a little advanced, but here is an example

g.withSideEffect('ids',['3','4','xyz','abc']).
  withSideEffect('p',['xyz': ['type':'dog'],'abc':['type':'cat']]).
  V('3','4','xyz','abc').
  id().fold().as('found').
  select('ids').
  unfold().
  where(without('found')).as('missing').
  addV('new-vertex').
    property(id,select('missing')).
    property('type',select('p').select(select('missing')).select('type'))

That query will look for a set of vertices, figure out which ones exist, and for the rest use the ID values and properties from the map called 'p' to create the new vertices. You can build on this pattern a great many ways and I find it very useful until mergeV and mergeE are more broadly available

You can also use the list of IDs in the query to check which ones exist. However, this may lead to inefficient query plans depending on the given implementation:

g.withSideEffect('ids',['3','4','xyz','abc']).
  withSideEffect('p',['xyz': ['type':'dog'],'abc':['type':'cat']]).
  V().
  where(within('ids')).
    by(id).
    by().
  id().fold().as('found').
  select('ids').
  unfold().
  where(without('found')).as('missing').
  addV('new-vertex').
    property(id,select('missing')).
    property('type',select('p').select(select('missing')).select('type'))

This is trickier than the first query, as the V step cannot take a traversal. So you cannot do V(select('ids')) in Gremlin today.