I found a "friends of friend" traversal query which meets my basic needs to get the friends of friends (friends of friend Query in ArangoDB 3.0). I have modified it slightly to make it work with "The Knows_Graph" example found in the documentation and I've added some extra people (https://docs.arangodb.com/3.11/graphs/example-graphs/#knows-graph)
My query uses Dave as the starting point and looks for his 2nd degree friends via Bob and Lucy. The script works fine but I also want it to include the 1st degree friends (bob and lucy) in the query result. I can do this by setting the minimum depth to 1, however if I do that I doesn't differentiate the depth of Bob and Lucy (see json output), so I wont be able to tell on a bigger graph who is 1st degree and who is 2nd degree
Sample code for min depth of 2
LET person = DOCUMENT("persons/@persons/dave")
LET foaf = (
FOR v IN 2..2 ANY person knows
RETURN v
)
RETURN MERGE(person, { foaf } )
The sample uses the "knows" edge collection and "person" collection
Here is the json output if I have a min depth of 1 and a max depth of 2. As you can see bob and lucy are show on the same collection level as the others. I want to find a way to display them as 1st level somehow without over-complicating the query or causing performance issues.
[
{
"_id": "persons/dave",
"_key": "dave",
"_rev": "_U7wRsJG--_",
"name": "Dave",
"foaf": [
{
"_key": "lucy",
"_id": "persons/lucy",
"_rev": "_U8--wPq---",
"name": "Lucy"
},
{
"_key": "henry",
"_id": "persons/henry",
"_rev": "_U8-_FNa---",
"name": "Henry"
},
{
"_key": "bob",
"_id": "persons/bob",
"_rev": "_U7wRsJC--_",
"name": "Bob"
},
{
"_key": "charlie",
"_id": "persons/charlie",
"_rev": "_U7wRsJG---",
"name": "Charlie"
},
{
"_key": "alice",
"_id": "persons/alice",
"_rev": "_U7wRsJC---",
"name": "Alice"
},
{
"_key": "eve",
"_id": "persons/eve",
"_rev": "_U7wRsJG--A",
"name": "Eve"
}
]
}
]
With the following query you get the depth information on every of your friends.
LET person = DOCUMENT("persons/@persons/dave")
LET foaf = (
FOR v, e, p IN 1..2 ANY person knows
RETURN {v, depth: LENGTH(p.edges)}
)
RETURN MERGE(person, { foaf } )
The output should look like:
[
{
"_id": "persons/dave",
"_key": "dave",
"_rev": "_U8e0Ube---",
"foaf": [
{
"v": {
"_key": "lucy",
"_id": "persons/lucy",
"_rev": "_U8e0Y2u---"
},
"depth": 1
},
{
"v": {
"_key": "bob",
"_id": "persons/bob",
"_rev": "_U8ezwCm---"
},
"depth": 1
},
{
"v": {
"_key": "charlie",
"_id": "persons/charlie",
"_rev": "_U8e0-Oe---"
},
"depth": 2
},
{
"v": {
"_key": "eve",
"_id": "persons/eve",
"_rev": "_U8e0loy---"
},
"depth": 2
},
{
"v": {
"_key": "alice",
"_id": "persons/alice",
"_rev": "_U8e0ptu---"
},
"depth": 2
}
]
}
]
If you wan to group the friends of every depth together your query could look like:
LET person = DOCUMENT("persons/@persons/dave")
LET foaf = (
FOR v, e, p IN 1..2 ANY person knows
COLLECT depth = LENGTH(p.edges) INTO s KEEP v
RETURN {depth, foaf: s[*].v}
)
RETURN MERGE(person, { foaf } )
The output should look like:
[
{
"_id": "persons/dave",
"_key": "dave",
"_rev": "_U8e0Ube---",
"foaf": [
{
"depth": 1,
"foaf": [
{
"_key": "lucy",
"_id": "persons/lucy",
"_rev": "_U8e0Y2u---"
},
{
"_key": "bob",
"_id": "persons/bob",
"_rev": "_U8ezwCm---"
}
]
},
{
"depth": 2,
"foaf": [
{
"_key": "charlie",
"_id": "persons/charlie",
"_rev": "_U8e0-Oe---"
},
{
"_key": "eve",
"_id": "persons/eve",
"_rev": "_U8e0loy---"
},
{
"_key": "alice",
"_id": "persons/alice",
"_rev": "_U8e0ptu---"
}
]
}
]
}
]
UPDATE
If you need more information about the relations between the people you can return the path instead of the vertices. The path (p
) includes all visited edges (knows relations) and all vertices (persons).
For more information about the AQL traversal syntax: see docs.
LET person = DOCUMENT("persons/@persons/dave")
LET foaf = (
FOR v, e, p IN 1..2 ANY person knows
COLLECT depth = LENGTH(p.edges) INTO s KEEP p
RETURN {depth, foaf: s[*].p}
)
RETURN MERGE(person, { foaf } )