Search code examples
graphqlfaunadb

How to connect Many-to-one relations in FaunaDB


I’ve got the following GraphQL schema uploaded to my FaunaDB:

type RSheet @collection(name: "sheets") {
  columns: [RColumn!]! @relation
  sections: [RSection]!
}

type RColumn @collection(name: "columns") {
  label: String!
  sheet: RSheet!
}

type RSection @embedded {
  label: String
  items: [[RItem!]]!
}

type RItem @embedded {
  value: String
  form: RItemForm
  column: RColumn!
}

enum RItemForm {
  STRING
}

That is a sheet with columns and a number of sections with items that make the rows of a table.


Now, I’ve created a sheet as well as two columns.

“sheets” collection in the database

{
  "ref": Ref(Collection("sheets"), "304268724760740364"),
  "sections": [
    {
      "label": null,
      "items": []
    }
  ]
}

“columns” collection in the database

{
  "ref": Ref(Collection("columns"), "304268724764934668"),
  "label": "Begin",
  "sheet": Ref(Collection("sheets"), "304268724760740364")
},
{
  "ref": Ref(Collection("columns"), "304268724776469004"),
  "label": "End",
  "sheet": Ref(Collection("sheets"), "304268724760740364")
}

All this works fine so far. I can create sheets and/or columns, update, and delete them.


However, if I want to add a section item using FaunaDB’s GraphQL I can’t connect the item’s columns. I get an error stating that I have to provide the column’s ID!:

Screenshot of the GraphQL error

When I do so, only the ID is written to the database and a connection Ref(…) is not created:

“sheets” collection in the database

{
    "ref": Ref(Collection("sheets"), "304268724760740364"),
    "sections": [
      label: null
      {
        "items": [
          [
            {
              "value": "Item 1",
              "column": "304268724791149068"  /// EXPECTED: Ref(Collection("columns"), "304268724791149068")
            }
          ]
        ]
      }
    ]
  }

What am I missing?


Solution

  • You cannot create relations inside embedded types. From the docs on relations:

    The relationship recognition algorithm looks at every field for all non-embedded types

    I do think it would be nice to have relationships work through @embedded types, but that is not what they were really intended for, so it is not supported.

    You will need to rework your schema so that each connection is in an non-embedded type. Also, the 2-dimensional array is also not possible with connections.

    Example

    Consider the following schema

    type RSheet @collection(name: "sheets") {
      columns: [RColumn!]! @relation
      sections: [RSection]! @relation
    }
    
    type RColumn @collection(name: "columns") {
      label: String!
      sheet: RSheet! @relation
      items: [RItem!] @relation
    }
    
    type RSection @collection(name: "section") {
      label: String
      sheet: RSheet @relation
      items: [RSectionItemList!]! @relation
    }
    
    type RSectionItemList @collection(name: "section_item_list") {
      section: RSection! @relation
      items: [RItem!]! @relation
    }
    
    type RItem @collection(name: "item") {
      value: String
      form: RItemForm
      column: RColumn! @relation
      list: RSectionItemList @relation
    }
    
    enum RItemForm {
      STRING
    }
    

    Note how I split the 2-dimensional array into a list of wrapper list objects.

    A sheet and columns could be created like this:

    enter image description here

    And items added like this:

    enter image description here