0

I am trying to design a schema for an application and I have a problem that I can't solve. Here is a detail of the application

User A LIKES User B User B MATCHS User B Now User A and User B can start chatting with each others.

I also keep track of who visited each profile User A VISITED BY User B User A Visited BY User C

In the application, I have Me type with details of the user running the app. I have a me query that looks like this:

me {
  id
  name
  email
  ...
  ...
  likes {  ## users who liked me
    nextToken
    edges {
      node { ## user
        id
        name
        ...
      }
    }
  }
  matchs { ## users who matched with me
    nextToken
    edges {
      node { ## user
        id
        name
        ...
        ...
      }
    }
  } 
  Vists { ## users who visited me
    nextToken
    edges {
      node { ## 
        id
        name
        ...
        ...
      }
    }
  }
}

In addition to that, I have listUsers query that list users nearby to Me and looks something like this:

listUsers {
  nextToken
  total
  edges {
    distance
    node {  ## user
      id
      name
      ...
      ...
    }
  }
}

MY QUESTION Since there is a relationship between users (LIKED_BY, MATCHED_WITH) where do I use this relationship in my schema such that it is cashable. Keep in mind the relationship can change at the client from NO_RELATIONSHIP to LIKED_BY to MATCHED_WITH so if the relationship is duplicated in multiple places, this will be a problem.

I would really appreciate any help as I am out of ideas.

Thanks in advance.

Aimn Blbol
  • 907
  • 11
  • 20

2 Answers2

0

In the GraphQL schema you'd generally make links like this explicit references to the other object.

type User {
  id: ID!
  ...
  matches: [User!]  # actual users, not their IDs
  likes: [User!]
  visitedBy: [User!]
}

In your top-level Query type you can return the current user

type Query {
  me: User
}

Now if I want the names and email addresses of people who have visited me, I can find out

query WhoVisitedMe {
  me {
    visitedBy { name, email }
  }
}

You can traverse this graph, for example, to get recommendations: for people who visit you, who do they like?

query WhoDoVisitorsLike {
  me {
    visitedBy {
      likes {
        id
        name
      }
    }
  }
}

Your application's resolver code would need to fill in these object references.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • David, thanks for your help. I am aware of what you said. My only concern is in the relationship between users. Where do I place it in the schema. The relationship should be cashable at the client side because it can change by the users. Thanks – Aimn Blbol Sep 21 '20 at 16:44
  • In the example schema I showed above, the `User` object type has a `likes` field, whose value is a list of other `User` objects. That's the relationship. There are extended patterns like the [Relay connection pattern](https://relay.dev/graphql/connections.htm) that include pagination and other functionality if you think this will be a large collection. – David Maze Sep 21 '20 at 17:14
  • Forget about the Me query for a second and think of the listUsers search query which should give you results as described above. Where do you place the relationship in this query? Whenever I view the list of users, I would like to know relationship between that user and My self. The same apply for the list of people who visited Me. – Aimn Blbol Sep 21 '20 at 17:36
  • I think I'm a little unclear what you mean by "relationship" here. Do you mean any connection between any kinds of objects (like an SQL foreign key, or a "has-many" relationship in an ORM)? Or any of these kinds of "user A is connected to user B" links? Do you want an abstract notion of any sort of connection? The ability to traverse these links in reverse ("who likes this user")? – David Maze Sep 21 '20 at 18:19
  • The relationship between users is a many to many relationship. So user A likes many Users and many users can like user A. While listing users in the search query, I need to be able to know the relationship between Me and the users This way I can tell Me to like or match the Users. Also, if I know the relationship between Me and the user, I can show an icon on the user to indicate the relationship. – Aimn Blbol Sep 21 '20 at 18:30
0

You clarified in a comment:

While listing users in the search query, I need to be able to know the relationship between Me and the users

That is, you're trying to ask about some user

type User {
  relationToMe: [RelationshipType!]
}

The relationToMe field can have any number (including zero) of relationship types; you can define those as a GraphQL enum

enum RelationshipType {
  LIKES, LIKED_BY,
  VISITED, VISITED_BY,
  MATCHES               # bidirectional
}

Then in your query you can ask

query FindSomeUsers($input: SearchUsersInput!) {
  searchUsers(input: $input) {
    users {
      id, name, email
      relationToMe
    }
  }
}

and get back a response like

{
  "data": {
    "searchUsers": {
      "users": [
        "id": "12345",
        "name": "John Smith",
        "email": "jsmith@example.com",
        "relationToMe": ["VISITED", "MATCHES"]
      ]
  }
}

You'd need to implement a custom resolver in your implementation to populate this field. If you had something like a many-to-many SQL join table, you could query that to fill in this field, if requested.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • In the past, I placed the relationship at the User but ran into couple issues. 1- relationship is really not part of the user (node) but rather should be part of the edge. 2- I have to worry too much about user.source. So I decided to move the relationship into the edge. Implementation got better but had to do more much more code. So, I thought I will check and see what other developers out there have to say. – Aimn Blbol Sep 21 '20 at 19:41