Gremlin - Choose one item at random

蹲街弑〆低调 提交于 2019-12-16 20:01:39

问题


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:

  1. Whether it has been liked by me
  2. 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]]]

回答1:


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:[]]]


来源:https://stackoverflow.com/questions/51388315/gremlin-choose-one-item-at-random

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!