Help with nested graphql query

When you define a Query field like this

findByParent(otherCollection._id: ID!,  name: String!): [NestedType!]

Since there is no directive provided, it defaults to @index. So the field is equivalent to this:

findByParent(otherCollection._id: ID!,  name: String!): [NestedType!] @index(name: "findByParent")

There is the matter that you cannot provide argument names with a . in them – it’s not valid GraphQL. But more importantly, for uploading a schema to Fauna, arguments for an @index field:

  • must match a field name in your return type.
  • that field in your return type must be a GraphQL Scalar field. That is, it can NOT be another user-defined type.

The return type here is NestedType. So the available names for arguments are name, and that’s it.

You can check out this previous topic for some additional discussion on how GraphQL generates the final schema. Understanding fauna auto-generation from schema

Using @resolver

You will have to create a custom resolver. In your case, you should be able to create a single Index and pass both the OtherCollection ID and the NestedType name to it. This is possible because Fauna stores references for one-to-many relationships in the “many” side. If you look up a NestedType in the Dashboard or the Shell, it should look something like this:

{
  ref: Ref(Collection("NestedType"), "101"),
  ts: 163452340923678,
  data: {
    name: "Thing1",
    otherCollection: Ref(Collection("OtherCollection"), "42")
  }
}

Since the reference is stored there, we can Index it!

CreateIndex({
  name: "NestedType_by_otherCollection_name",
  terms: [
    { field: ["data", "otherCollection"] },
    { field: ["data", "name"] },
  ]
})

Here is a UDF that uses the Index

CreateFunction({
  name: "findByParent",
  // role: ??? // apply an appropriate role
  body: Query(Lambda(
    ["otherCollection_id", "name"],
    Let(
      {
        otherCollection_ref: Ref(Collection("OtherCollection"), Var("otherCollection_id")),
        paginatedResults: Paginate(
          Match(
            Index("NestedType_by_otherCollection_name"),
            [Var("otherCollection_ref"), Var("name")]
        )
      },
      Select("data", Var("paginatedResults"), [])
    )
  ))
})

Add to your GraphQL schema like this

type Query {
  findByParent(otherCollection_id: ID!, name: String!): [NestedType!]
    @resolver(name: "findByParent")
}

If you need pagination, then you’ll need to update the directive to @resolver(name: "findByParent", paginated: true) and update your UDF to accept the pagination arguments.

1 Like