Help with nested graphql query

I have 2 graphql types that look like this


type OtherCollection {
 name:String
  nestedTypes: [NestedType!]
}

type NestedType {
  name: String!
  otherCollection: OtherCollection @relation
}

I want to do a search on NestedType by OtherCollection._id and name

ideally it would look something like this

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

that of course does not work but I can’t find the right way to do that in a graphql query.

I searched in the forum but I could not find an answer

OtherCollection can have thousands of NestedType and I want only a subset of them without having to do a for loop on thousands for entities
Thank you all in advance

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

This is awesome!
I can’t thank you enough, I am a huge huge fan of Fauna and this kind of support is top notch.
I am very thankful, this was incredibly helpful thank you!!!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.