Given a many-to-many relationship, why does GraphQL `connect` return an error?

Given the following schema:

type Article {
  headline: String
  author: [Author]
}

type Author {
  name: String
  contributed: [Article]
}

type Query {
  getArticles: [Article]
}

With the the following items, in their respective collections:

{
  "ref": Ref(Collection("Article"), "322054626916433992"),
  "ts": 1643394285230000,
  "data": {
    "headline": "Foo",
  }
}
{
  "ref": Ref(Collection("Author"), "322054459536441415"),
  "ts": 1643393916590000,
  "data": {
    "name": "nk"
  }
}

The following mutation:

mutation Update{
  updateArticle(id: "322054626916433992" data: {
    author: {
      connect: "322054459536441415"
    }
  }) {
    headline
    author {
      name
    }
  }
}

Returns the error:

{
  "data": null,
  "errors": [
    {
      "message": "Expected type 'String', found '{connect: \"322054459536441415\"}'. String value expected (line 4, column 20):\n    data: {author: {connect: \"322054459536441415\"}}\n                   ^",
      "locations": [
        {
          "line": 4,
          "column": 20
        }
      ]
    }
  ]
}

Why? Why does connect not seem to work? What’s going on here?

I would expect that this would add a ref to the Article.author field to the author, and a ref on the Author.contributed field to the article.

The mutation without the connect:

mutation Update{
  updateArticle(id: "322064934066192455" data: {
    author: "322064951688560713"
  }) {
    headline
    author {
      name
    }
  }
}

Creates the response:

{
  "data": {
    "updateArticle": {
      "headline": "Cool Article",
      "author": [
        {
          "name": "nk"
        }
      ]
    }
  }
}

And updates the item in the collection to:

{
  "ref": Ref(Collection("Article"), "322064934066192455"),
  "ts": 1643404054770000,
  "data": {
    "headline": "Cool Article",
    "author": [
      Ref(Collection("Author"), "322064951688560713")
    ]
  }
}

But this doesn’t change the author item at all, so I am unable to get the articles an author references.

Do just have to perform updates on both items at the same time? Because that’s a downer!

mutation Update{
  updateArticle(id: "322064934066192455" data: {
    author: "322064951688560713"
  }) {
    headline
    author {
      name
    }
  }
  updateAuthor(id: "322064951688560713" data: {
    contributed: "322064934066192455"
  }) {
    name
    contributed {
      headline
    }
  }
}

I figured it out, the schema needs an explicit @relation directive:

type Article {
  headline: String
  author: [Author] @relation
}

type Author {
  name: String
  contributed: [Article] @relation
}

Thank you for coming to my TED talk.

1 Like