Is there any better way to friendship mutation

Hi I’m Ten

I developing a system of friendships

At first, I created a relations node between users, requestedBy and requestedTo, referring to the image below. But it seems that HasInverse is not possible in DQL, so it does not work 100% the same.
image

However, when creating the Mutation query, I was frustrated because I did not know how to get the relations node where both uid1 and uid2 are in requestedBy or requestedTo.

Next, I found facets and thought I could implement it, so I wrote the following code.
friendStatus 0 = Maybe they know each other.
friendStatus 1 = friend requested
friendStatus 2 = friend request received
friendStatus 3 = friend

upsert {
  query {
    q1(func: eq(uniqueUserId, "test1")) {
      u1 as uid
    }
    q2(func: eq(uniqueUserId,"test2"))
    {
      u2 as uid
		}
    
    q3(func: uid(u1))
		{
   		friends @filter(uid(u2)) @facets(gt(friendStatus,0)) @facets(currentStatus:friendStatus){
        requestExists as uid
    	}
		}
  }
  mutation @if(eq(len(requestExists),0)) {
    set {
      uid(u1) <friends> uid(u2) (friendStatus=1) .
      uid(u2) <friends> uid(u1) (friendStatus=2) .
    }
  }
  mutation @if(eq(currentStatus,2)){
    set{
      uid(u1) <friends> uid(u2) (friendStatus=3) .
      uid(u2) <friends> uid(u1) (friendStatus=3) .
    }
  }
    
}

If there is a better way, please let me know.

This is a specific thing in the GraphQL modeling. Won’t work easy in DQL as it does in GraphQL. But you can do with Upsert Mutation.

That is too much complex.

Why not just use mutiple edges?

  This will create a list a requests out of the box.

<0x1> <requestTo> <0x2> (since=2022-06-08) .
  
 
  This will record the acceptance.
  
<0x2> <accepted> <0x1> (since=2022-06-09) .
  

  Finally you can add them in both directions as friends.
  
  <0x2> <friends> <0x1> .
  <0x1> <friends> <0x2> .

You will have all information you need.

But if you wanna do something more “traceable”, you can add a node between them to represent the history of friendship.

Person A <=|=> FriendShipNode <=|=> Person B

This node “FriendShipNode” will point to both and record their relationship informations.

I am currently experimenting with FriendShipNode.

For example, if I have a node like this

friendShip {
requestedBy:uid
requestedTo:uid
since:dateTime
}

How can I query a Node where requestedBy or requestedTo contains both userA and userB?

Also, I would like to know the ideal query to retrieve only the node related to userA.

There are several ways. Here one I can think of.

If you don’t know the UIDs

{

  userA as var(func: eq(name, "UserA"))
  userB as var(func: eq(name, "UserB"))
  
  q(func: type(FriendShip)) @filter(uid_in(requestedBy, uid(userA)) AND uid_in(requestedTo, uid(userB))){
    requestedBy
    requestedTo
    since
  }
}

If you know the UIDs

{

  userA as var(func: uid(0x1))
  userB as var(func: uid(0x2))
  
  q(func: uid(0x33)) @filter(uid_in(requestedBy, uid(userA)) AND uid_in(requestedTo, uid(userB))){
    requestedBy
    requestedTo
    since
  }
}

From User B using Reverse edge index. Avoiding using such wide query as Type()

{
  
  userA as var(func: eq(name, "UserA"))
  userB as var(func: eq(name, "UserB"){
    BY as <~requestedBy>
  }
  
  q(func: uid(BY)) @filter(uid_in(requestedBy, uid(userA)) AND uid_in(requestedTo, uid(userB))){
    requestedBy #This needs a reverse index
    requestedTo #This needs a reverse index
    since
  }
}