Placing an index on a field in an embedded type

I borrowed this example from the Fauna docs for the @embedded directive:

type Address @embedded {
  street: String!
  city: String!
  zipCode: String!
}

type User @collection(name: "users") {
  name: String
  address: Address
}

I’d like to put a non-unique index on the zip code field but I can’t find the proper syntax. Up until this point my indices have been fairly simple, so my first try was the following:

type Query {
    findUsersByZipCode(zipCode: String!): [User!]
}

I get a syntax error on that. I’ve tried but I can’t seem to find the magic.
The one thing that works is moving zipCode from Address into User like this:

type Address @embedded {
  street: String!
  city: String!
}

type User @collection(name: "users") {
  name: String!
  address: Address!
  zipCode: String! @unique
}

That works but isn’t desirable.
Is this even doable?
Thank you

@oopfan I don’t think we support an Index on a field in embedded type automatically through GraphQL schema Import. A workaround is to create the Index manually on the embedded field, add a @resolver directive to the query and update UDF to use that Index.

I will get a ticket to Product to add this feature.

Hope this helps.

Hi @Jay-Fauna,

I have run into a similar issue trying to create in index using terms in an embedded field. Could you elaborate on the above schema by providing an example of the way @resolverwould be used in the GraphQL schema and the UDF to support it?

Following up for some further guidance here. @Jay-Fauna, can you help by giving an example of the type of resolver UDF mentioned? I have also had difficulty with manually defining indexes to achieve this result so help here would also be great.

@Darryl_Naidu, Here is an example.

Schema with an embedded object.

type Address @embedded {
  street: String!
  city: String!
  zipCode: String!
}

type User @collection(name: "users") {
  name: String
  address: Address
}

type Query {
  findUsersByZipcode(zipCode: String!): [User]! @resolver(name: "findUsersByZipcode", paginated: true)
}

Embedded objects do not have a Collection on their own. Therefore you cannot create an Index on its fields from GraphQL API. They are a part of the document they are embedded in.

GraphQL mutation to create a new User with Address embedded into it.

The document would look like this in the Collection users

Map(Paginate(Documents(Collection('users'))),Lambda('x',Get(Var('x'))))

{
  data: [
    {
      ref: Ref(Collection("users"), "291554958903345666"),
      ts: 1614307326130000,
      data: {
        name: "jay",
        address: {
          street: "Washington Ave",
          city: "New York",
          zipCode: "19045"
        }
      }
    }
  ]
}

Create an Index on the zipCode field.

CreateIndex(
{
name: "users_by_zipcode",
source: Collection("users"),
terms: [{field: ["data", "address", "zipCode"]}]
})

Test the above Index

Map(Paginate(Match(Index('users_by_zipcode'),"19045")),Lambda('x',Get(Var('x'))))

{
  data: [
    {
      ref: Ref(Collection("users"), "291554958903345666"),
      ts: 1614307326130000,
      data: {
        name: "jay",
        address: {
          street: "Washington Ave",
          city: "New York",
          zipCode: "19045"
        }
      }
    }
  ]
}

The Resolver(findUsersByZipcode(zipCode: String!): [User]! @resolver(name: "findUsersByZipcode", paginated: true) in the Schema file should have created a UDF.

Paginate(Functions())

{
  data: [Ref(Ref("functions"), "findUsersByZipcode")]
}

Update this UDF to use the above create Index.

Update(
  Function("findUsersByZipcode"),
  {
  body: Query(Lambda(["zipCode", "size", "after", "before"],
    Let(
      {
        match: Match(Index("users_by_zipcode"),Var("zipCode")),
        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"))))
    )
  ))
  }
)

Test this UDF (zipcode, size, after, before)

Call(Function("findUsersByZipcode"), ["19045", 3, null, null])

{
  data: [
    {
      ref: Ref(Collection("users"), "291554958903345666"),
      ts: 1614307326130000,
      data: {
        name: "jay",
        address: {
          street: "Washington Ave",
          city: "New York",
          zipCode: "19045"
        }
      }
    }
  ]
}

Finally, call from this UDF from the GraphQL query.