Understanding fauna auto-generation from schema

Fauna does not generate “all” queries by default. You have to add them. And really, the way you can most easily add them is the same way you would quickly add any indexed query.

Let’s set aside the “all” case for the moment. You can create an indexed query for Users by active for example.

type Query {
  # silly name so you know it is my own, not a fauna default one
  # note that `active` is spelled the same as the "term" that is desired.
  myUserByActiveStatusQuery(active: Boolean!): [User]
}

This automatically creates an index on User with term ['data', 'active']. If the spelling was off, it would still be created. If I did myUserByActiveStatusQuery(activeStatus: Boolean!): [User] by mistake, then the index would be created for term ['data', 'activeStatus'], regardless if it actually matched anything in the GraphQL schema.

The above is just shorthand for using the @index directive!

NOTE: the docs are bad at making it clear this exists, IMO. Examples leverage the short hand, but the page for the directive does not say it exists.

type Query {
  myUserByActiveStatusQuery(active: Boolean!): [User] @index(name: "myUserByActiveStatusQuery")
}

If you provide more than one argument to a query, it will generate an index with multiple terms.

type Query {
  playerByActiveAndRank(active: Boolean!, rank: Int!): [Player]
  #  remember shorthand for 
  playerByActiveAndRank(active: Boolean!, rank: Int!): [Player] @index(name: "playerByActiveAndRank")
}

So what happens when there are no arguments in the queries schema? You get an index with no terms! and that’s really just an “all” documents index. Doing nothing but this to your schema will give you an index that will result in all Players being returned. AND it will be a paginated query. You can replicate with an UDF, but then you need to add Pagination logic yourself if it is desired.

type Query {
  allPlayers: [Player]
}

You can do this multiple times with different names, and realize that there is nothing special about the name, and they will all return the same thing.

type Query {
  allPlayers: [Player]
  allPlayers2: [Player]
  allOfThePlayersForSure: [Player]
  aQueryWithoutTheWordPlayerButReturnsAllPlayers: [Player]
  ohWaitAMinute: [Player]
}

To finally answer your specific question

You did not share your Query definition. But:

This very specifically means that there is no field on type 'Query' that matches allPlayers. You need to add one.

also

I would advise a couple of things.

  1. consider using @index, or the short hand described, for the “all” queries. It’s WAY simpler than trying to define your own resolver.

  2. Note that creating a new “all” query is unfortunately a bit redundant. This is because there is the built in index that is accessible through the Documents function. So now you are maintaining multiple indexes even if you are only using one. To leverage Documentsfunction, you can use @resolver, but if you want the full functionality of a paginated query, then you need to mark paginated true.

type Query {
  allPlayers: [Player] @resolver(name: "all_players", paginated: true)
}

use Documents and pagination in your UDF

{
  name: "all_players",
  body: Query(Lambda(["size", "after", "before"],
    Let(
      {
        match: Documents(Collection("Player")),
        page: If(
          Equals(Var("before"), null),
          If(
            Equals(Var("after"), null),
              Paginate(Var("match"), { size: Var("size") }),
              Paginate(Var("match"), { size: Var("size"), after: Var("after") })
          ),
          Paginate(Var("match"), { size: Var("size"), before: Var("before") }),
        )
      },
      Map(Var("page"), Lambda("ref", Get(Var("ref"))))
    )
  ))
}

This is taken straight out of docs.

2 Likes