Graphene-Django: Concepts of Connections, Edges, and Nodes
Asked Answered
A

2

8

I just started experimenting with graphene-django/GraphQL and am pretty confused about the relay library that has been brought in for graphene-django. After running through the cookbook example (implementing it with my own models) and running a test query, upon POST the query gets transformed to a strangely nested object with edges and nodes. What are these and what are they doing?

{
  companies {
    edges {
      node {
       id
     }
    }
  }
}
Arliearliene answered 6/1, 2017 at 20:57 Comment(4)
I'm also new to Relay. This is a standard setup. Check out this explanation facebook.github.io/relay/graphql/connections.htmVlad
The reason this question came up was we wanted to use graphene-djano within our app without the relay dependency for filtering. I was able to find a technique to add filtering without using relay here linkArliearliene
I see what you mean. As noted in your link, the advantage of sticking with relay conventions is that graphene gives you a pre-built setup for paging. A GraphQL query with "pageInfo { hasNextPage hasPreviousPage startCursor endCursor }" works automatically.Vlad
We did discuss that as a pro, however, with the app we are building we decided it we'd rather have a cleaner query strings and query results over pagination. Worst case scenario, we'll attempt to roll our own pagination using filtering offsets and subsets.Arliearliene
B
8

Node

It may be worth mentioning that Node is part of the Facebook Relay specs (not GraphQL specs). However, most framework (Graphene included) implement this spec due to the close association between Relay and GraphQL.

Essentially Node is an interface that implements just an ID field, which is meant to be an globally unique identifier for an object. IDs are designed to be opaque (typical convention is to base64('type:id')), applications should not attempt to rely on this implementation detail.

Node is exposed as part of the root Query, where applications can query for entities with known ID in a convenient way, e.g. refetching, fetching fields that have not been fetched.

{
  node(id: ID!) {
    ... on User {
      id
      userId
      name 
    }
    ... on Company {
      id
      companyId
      owner: {
        userId
        name
      }
    }
    ...
  }
}

This provides the convenience of not having to define query point for every model you expose (e.g. message(messageId) or user(userId)). This also allows you to query for the object without transversing through an object path, example

{
  user {
    friends {
      pages {
        name
      }
    }
  }
}

// vs

{
  node(id) {
    ... on Page {
      name
    }
  }
}

Connection

Like Node, Connection is also part of the Relay specs that made its way to mainstream adoption.

At first glance, the concept of edges seems superfluous but it does solve some tricky use case. Consider the need to expose a many-to-many relationship like 'friends', typically implemented in a database with a join table.

+---------+         +------------+
| users   |         | friends    |
+---------+         +------------+
| user_id | <------ | left_id    |
| ....    |    \--- | right_id   |
+---------+         | created_at |
                    +------------+

It is now easy to display "Friends since [date here]" by exposing friends.created_at in the edge object.

{
  user {
    friends {
      edges {
        created_at  <---
        user {
          id
          userId
          name
        }
      }
    }
  }
}

edges essentially defines the relationship between nodes.

Bumblebee answered 28/7, 2017 at 9:7 Comment(0)
E
0

M2M relationship between Atable and Btable must to be implemented by third link (join) table ABLink, which must have at least two foreign keys:

+------+------+------------+--------+  
| A_id | B_id | Created_at | Status |  
+------+------+------------+--------+  

Is it right to say for m2m that edge represent such link (join) table in database? So then query for that would be:

{
  Atable {
    ABLink {
      edges {
        Created_at
        Status
        Btable {
          Btable_id
          Btable_column_1
          Btable_column_2
          ...
        }
      }
    }
  }
}
Expiation answered 21/2, 2018 at 20:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.