0

From the following graph in the Tickerpop recipes:

  g.addV("user").property("name", "alice").as("u1").
  addV("user").property("name", "jen").as("u2").
  addV("user").property("name", "dave").as("u3").
  addV("movie").property("name", "the wild bunch").as("m1").
  addV("movie").property("name", "young guns").as("m2").
  addV("movie").property("name", "unforgiven").as("m3").
  addE("friend").from("u1").to("u2").
  addE("friend").from("u1").to("u3").
  addE("like").from("u2").to("m1").
  addE("like").from("u2").to("m2").
  addE("like").from("u3").to("m2").
  addE("like").from("u3").to("m3")

How can i query friends of a specific user in descending order of how many common movies they have liked? Thanks

Kelvin Lawrence
  • 14,674
  • 2
  • 16
  • 38
Programjon
  • 23
  • 6

1 Answers1

1

I added some more edges to the graph to make the results more interesting.

  g.addV("user").property("name", "alice").as("u1").
  addV("user").property("name", "jen").as("u2").
  addV("user").property("name", "dave").as("u3").
  addV("movie").property("name", "the wild bunch").as("m1").
  addV("movie").property("name", "young guns").as("m2").
  addV("movie").property("name", "unforgiven").as("m3").
  addE("friend").from("u1").to("u2").
  addE("friend").from("u1").to("u3").
  addE("friend").from("u2").to("u3").
  addE("friend").from("u2").to("u1").
  addE("like").from("u2").to("m1").
  addE("like").from("u2").to("m2").
  addE("like").from("u3").to("m2").
  addE("like").from("u3").to("m3").
  addE("like").from("u1").to("m1").
  addE("like").from("u1").to("m2")  

We can then, for example, find Jen and collect the movies Jen likes and then find Jen's friends and count the number of movies they each like in common.

gremlin> g.V().
......1>   has('name','jen').as('jen').
......2>   sideEffect(out('like').store('movies')).
......3>   out('friend').
......4>   group().
......5>     by("name").
......6>     by(out('like').where(within('movies')).count())    


==>[dave:1,alice:2]    

You could also go one step further and order the results in either ascending or descending order.

gremlin> g.V().
......1>   has('name','jen').as('jen').
......2>   sideEffect(out('like').store('movies')).
......3>   out('friend').
......4>   group().
......5>     by("name").
......6>     by(out('like').where(within('movies')).count()).
......7>     order(local).
......8>       by(values,desc)  

==>[alice:2,dave:1]     

UPDATED to add an example where other information is part of the result.

gremlin> g.V().
......1>   has('name','jen').as('jen').
......2>   sideEffect(out('like').store('movies')).
......3>   out('friend').
......4>   group().
......5>     by(valueMap(true)).
......6>     by(out('like').where(within('movies')).count()).
......7>     order(local).
......8>     by(values,asc)    

==>[[id:61353,label:user,name:[dave]]:1,[id:61349,label:user,name:[alice]]:2] 

To omit the counts from the result

gremlin> g.V().
......1>   has('name','jen').as('jen').
......2>   sideEffect(out('like').store('movies')).
......3>   out('friend').
......4>   group().
......5>     by(valueMap(true)).
......6>     by(out('like').where(within('movies')).count()).
......7>     order(local).
......8>     by(values,asc).
......9>   select(keys)  

==>[[id:61353,label:user,name:[dave]],[id:61349,label:user,name:[alice]]]  
Kelvin Lawrence
  • 14,674
  • 2
  • 16
  • 38
  • suppose i want the response to contain all properties of the user vertices - let's say user also has a string property called "avatarUrl" in addition to "username" - how can i render this along with the username in the response? do i create another sideEffect? basically, i want to return an array of user dictionaries with each dictionary containing all the key/value pairs of the user rather than the single k/v pair in the example above. i still want to order the results by the count of common ratings, but i do not need to render the numeric count. – Programjon Feb 01 '22 at 17:50
  • so basically [{"username": "alice", "avatarUrl": "/sdjhfgsg/test.jpg"}, {"username": "dave", "avatarUrl": "/djhsfghsg/test1.jpg"}] – Programjon Feb 01 '22 at 17:52
  • You can change the `group` to use a `valueMap` - I'll update the answer with and example. Note that `valueMap` can take a list of the properties you want included as parameters. – Kelvin Lawrence Feb 01 '22 at 17:57
  • If you don't want to include the actual count in the result you can just select the `keys` from the map created by `group` – Kelvin Lawrence Feb 01 '22 at 18:00
  • Thanks again, Kelvin. You're a huge help! – Programjon Feb 01 '22 at 18:35
  • @kevin-lawrence - i have the results that i need now, thanks again. one last question on this. the results from this query 'g.V('a2661f57-8aa7-4e5c-9c89-55cf9b7e4cf8').as('self') .sideEffect(out('rated').store('movies')) .out('friended') .group() .by(valueMap(true).by(unfold())) .by(out('rated').where(within('movies')).count()) .order(local) .by(values,desc) .unfold() .select(keys)' – Programjon Feb 02 '22 at 16:45
  • return results in this format: {: 'fdc45bd3-be08-4716-b20f-b4f04987c5e0', : 'user', 'username': 'elin102dev', 'name': 'elin obrien', 'avatarUrl': 'public/avatars/fdc45bd3-be08-4716-b20f-b4f04987c5e0.jpg'}. how can i project or change the T.id and T.label keys in the results to just "id" and "label"? – Programjon Feb 02 '22 at 16:47
  • You can still select from the map using `T.id` and `T.label` as the key names which might be the simplest thing to do. – Kelvin Lawrence Feb 02 '22 at 17:26