How to construct a query collecting all friends?

I created the following query:

{
	users(func: type(User)){
    xid
    friends: friended OR ~friended {
      xid
    }
  }
}

But I’d like the json response to be fo the form:

{
  "users": [
    {
       "xid": "1",
       "friends": [
         {
           "xid": "2"
         },
         ...
       ]
    },
    {
       "xid": "2",
       "friends": [
          {
             "xid": "1"
          }
       ]
    }
   ...
  ]
}

I'm having a terrible time figuring out how to restructure my query. Thoughts?

This syntax isn’t supported.

Feels like your query should look like this:

{
  var(func: type(User)) {
    F as friended
    F2 as ~friended
  }

   allFriends(func: uid(F,F2)){
    xid
    name
  }
}

Thanks for the reply. So that query seems to return all friends in the graph, but doesn’t associate the friends to their respective users. For example, the query returns:

{
  "data": {
    "allFriends": [
      {
        "xid": "0"
      },
      {
        "xid": "1"
      },
      ...

Is it not possible to write a query that returns something like this:

{
  "data": {
    "users": [
      {
        "xid": "1",
        "friends": [
          {
            "xid": "2"
          }
        ]
      },
      {
        "xid": "2",
        "friends": [
          {
            "xid": "1"
          }
        ]
      }
    ]
  }
}

Umm… would this work?

query(func: type(Person)) {
        name
        friend{name}
        ~friend{name}
    }

It collects all friends but under two different headings (friend and ~friend).

I think I’m stuck w/ that approach as well. I’ll collect friended and friended_me separately, and just concat them in application code as friends :unamused:

1 Like

Sorry, Michael,

I still haven’t figured out your goal. When I read it, I thought you wanted to collect all friends in both directions and display them in a result. If you can explain exactly what you want, I’m sure it’s possible. Your example after my answer would take me to the same point as @Anurag.

But, looking at your last comment, maybe you want to know the consolidation of my friends and the friends who have me as a friend. Same concept of “knowing who I’m following and following me back”, is that it?

@MichelDiz think of friend as an undirected edge, then <A> <friend> <B> would imply that <B> <friend><A>. Under such settings @mvpmvh wants all friends of A. Currently my query gives all the friends under two separate headings i.e friends and ~friends.

Is there a way to combine that under one heading for each user?

No, cuz reverse edge is another edge even using the same name. In Dgraph, there is only one direction. Reverse edges are just indexing edges pretending to be reverse. You won’t “merge” them.

Also, this kind of modeling would be confusing. As reverse edges are just indexes. You can’t take it as part of the original edge. Because two different pieces of information cannot occupy the same space. Also said, Isaac Newton (I’m kidding).

Imagine a parallel world where Dgraph did not support reverse edges. In practice, you should have two edges to represent this situation and replicate the information between them.

e.g.
<A> <friend> <B> .

How would we know that they are friends? without a reverse edge. In that case above they are not. In this modeling, it seems more that there is an intention of User A to be friend with User B.

In order to know that A and B are friends, it is necessary to add this information also in node B. Without this there is no way to think that they are in fact friends.

<B> <friend> <A> .

If we use reverse edges, you can assume that they are friends implicitly, but you lose control of the logic of “send a friend request and wait to be accepted” (you know?) That could be explicit in both nodes. A and B.

In modeling, IMHO, we should never consider reverse edges as facts. They are only complementary information. Maybe to know “what friend requests have user A” or other purposes.

Here follows an example with sample dataset

{  
  G as var(func: type(User), first:1) {
    F as friend
    F2 as ~friend 
 }
  
 result(func: uid(G)) {
 	name
  requestsLeft : friend @filter(NOT uid(F2)) {
    name
  }
  accepted : ~friend @filter(uid(F)) {
    name
  }
    allFriends :friend {
    name
  }
 }
}

Result

{
  "data": {
    "result": [
      {
        "name": "User 3",
        "requestsLeft": [
          {
            "name": "User 2"
          }
        ],
        "accepted": [
          {
            "name": "User 4"
          },
          {
            "name": "User 1"
          }
        ],
        "allFriends": [
          {
            "name": "User 4"
          },
          {
            "name": "User 1"
          },
          {
            "name": "User 2"
          }
        ]
      }
    ]
  }
}

Second query

{  
  G as var(func: eq(name, "User 7")) {
     F as friend
     F2 as ~friend
 }
  
 result(func: uid(G)) {
 	name
  requestsWaitingToBeAccepted : friend @filter(NOT uid(F2)) {
    name
  }
  requestingMeFriendShip : ~friend @filter(NOT uid(F))  {
    name
  }
  accepted : ~friend @filter(uid(F)) {
    name
  }
    allFriends :friend {
      name
  }
 }
}

Result

{
  "data": {
    "result": [
      {
        "name": "User 7",
        "requestsWaitingToBeAccepted": [
          {
            "name": "User 5"
          },
          {
            "name": "User 1"
          }
        ],
        "requestingMeFriendShip": [
          {
            "name": "User 8"
          },
          {
            "name": "User 9"
          }
        ],
        "accepted": [
          {
            "name": "User 6"
          }
        ],
        "allFriends": [
          {
            "name": "User 5"
          },
          {
            "name": "User 6"
          },
          {
            "name": "User 1"
          }
        ]
      }
    ]
  }
}

Sample

{
   "set": [
      {
         "uid": "_:User1",
         "dgraph.type": "User",
         "name": "User 1",
         "friend": [
            {
               "uid": "_:User2"
            },
            {
               "uid": "_:User3"
            },
            {
               "uid": "_:User4"
            }
         ]
      },
      {
         "uid": "_:User2",
         "dgraph.type": "User",
         "name": "User 2",
         "friend": [
            {
               "uid": "_:User1"
            }
         ]
      },
      {
         "uid": "_:User3",
         "dgraph.type": "User",
         "name": "User 3",
         "friend": [
            {
               "uid": "_:User1"
            },
            {
               "uid": "_:User2"
            },
            {
               "uid": "_:User4"
            }
         ]
      },
      {
         "uid": "_:User4",
         "dgraph.type": "User",
         "name": "User 4",
         "friend": [
            {
               "uid": "_:User1"
            },
            {
               "uid": "_:User3"
            },
            {
               "uid": "_:User5"
            }
         ]
      },
      {
         "uid": "_:User5",
         "dgraph.type": "User",
         "name": "User 5",
         "friend": [
            {
               "uid": "_:User1"
            }
         ]
      },
      {
         "uid": "_:User6",
         "dgraph.type": "User",
         "name": "User 6",
         "friend": [
            {
               "uid": "_:User1"
            },
            {
               "uid": "_:User5"
            },
            {
               "uid": "_:User7"
            }
         ]
      },
      {
         "uid": "_:User7",
         "dgraph.type": "User",
         "name": "User 7",
         "friend": [
            {
               "uid": "_:User1"
            },
            {
               "uid": "_:User5"
            },
            {
               "uid": "_:User6"
            }
         ]
      },
      {
         "uid": "_:User8",
         "dgraph.type": "User",
         "name": "User 8",
         "friend": [
            {
               "uid": "_:User7"
            }
         ]
      },
      {
         "uid": "_:User9",
         "dgraph.type": "User",
         "name": "User 9",
         "friend": [
            {
               "uid": "_:User7"
            }
         ]
      }
   ]
}
1 Like