Consider me as 'user' 1. The aim of the query is to get the posts 'posted' by the people I follow and for each of those posts check:
- Whether it has been liked by me
- Whether it has been liked by anyone else that I follow and if yes choose one of those users at random to return
Sample data:
g.addV('user').property('id',1).as('1')
addV('user').property('id',2).as('2').
addV('user').property('id',3).as('3').
addV('user').property('id',4).as('4').
addV('post').property('postId','post1').as('p1').
addV('post').property('postId','post2').as('p2').
addE('follow').from('1').to('2').
addE('follow').from('1').to('3').
addE('follow').from('1').to('4').
addE('posted').from('2').to('p1').
addE('posted').from('2').to('p2').
addE('liked').from('1').to('p2').
addE('liked').from('3').to('p2').
addE('liked').from('4').to('p2').iterate()
Query: (As answered here: Graph/Gremlin for social media use case)
g.V().has('id',1).as('me').out('follow').aggregate('followers').out('posted').group().by('postId').by(project('likedBySelf','likedByFollowing').by(__.in('liked').where(eq('me')).count()).by(__.in('liked').where(within('followers')).order().by(shuffle).values('id').fold()))
Output:
[post1:[likedBySelf:0,likedByFollowing:[]],post2:[likedBySelf:1,likedByFollowing:[4,3]]]
This query is able to shuffle the values but shows all of the 'id's, now I want to select only the first 'id'. Using .next() instead of .fold() causes exception java.util.NoSuchElementException
Is it possible to choose randomly without having to evaluate all the traversals first and then shuffling them?
Desired Output:
[post1:[likedBySelf:0,likedByFollowing:[]],post2:[likedBySelf:1,likedByFollowing:[3]]]
Or
[post1:[likedBySelf:0,likedByFollowing:[]],post2:[likedBySelf:1,likedByFollowing:[4]]]
You're pretty close to your answer:
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV('user').property('id',1).as('1').
......1> addV('user').property('id',2).as('2').
......2> addV('user').property('id',3).as('3').
......3> addV('user').property('id',4).as('4').
......4> addV('post').property('postId','post1').as('p1').
......5> addV('post').property('postId','post2').as('p2').
......6> addE('follow').from('1').to('2').
......7> addE('follow').from('1').to('3').
......8> addE('follow').from('1').to('4').
......9> addE('posted').from('2').to('p1').
.....10> addE('posted').from('2').to('p2').
.....11> addE('liked').from('1').to('p2').
.....12> addE('liked').from('3').to('p2').
.....13> addE('liked').from('4').to('p2').iterate()
gremlin> g.V().has('id',1).as('me').
......1> out('follow').
......2> aggregate('followers').
......3> out('posted').
......4> group().
......5> by('postId').
......6> by(project('likedBySelf','likedByFollowing').
......7> by(__.in('liked').where(eq('me')).count()).
......8> by(__.in('liked').where(within('followers')).order().by('id',shuffle).values('id').limit(1).fold()))
==>[post2:[likedBySelf:1,likedByFollowing:[3]],post1:[likedBySelf:0,likedByFollowing:[]]]
I pretty much just added limit(1)
so that only the first item after shuffle
is selected. It took a few executions but I was able to see both of the outputs you were looking for with this method. As I suggested on your other question, you might also use sample(1)
:
gremlin> g.V().has('id',1).as('me').
......1> out('follow').
......2> aggregate('followers').
......3> out('posted').
......4> group().
......5> by('postId').
......6> by(project('likedBySelf','likedByFollowing').
......7> by(__.in('liked').where(eq('me')).count()).
......8> by(__.in('liked').where(within('followers')).sample(1).values('id').fold()))
==>[post2:[likedBySelf:1,likedByFollowing:[3]],post1:[likedBySelf:0,likedByFollowing:[]]]
gremlin> g.V().has('id',1).as('me').
......1> out('follow').
......2> aggregate('followers').
......3> out('posted').
......4> group().
......5> by('postId').
......6> by(project('likedBySelf','likedByFollowing').
......7> by(__.in('liked').where(eq('me')).count()).
......8> by(__.in('liked').where(within('followers')).sample(1).values('id').fold()))
==>[post2:[likedBySelf:1,likedByFollowing:[4]],post1:[likedBySelf:0,likedByFollowing:[]]]