Unique index on a couple of fields

Assuming a OrgMembers collection containing objects with org and member properties. How can we create a unique constraint for org/member couple? (e.g: I don’t want to have twice the same user in the same org).

Example data:

{
  "ref": Ref(Collection("OrgMembers"), "295386899698156033"),
  "ts": 1617961749660000,
  "data": {
    "createdAt": Time("2021-04-09T09:49:09.472Z"),
    "org": Ref(Collection("Orgs"), "295386899697107457"),
    "role": "admin",
    "user": Ref(Collection("Users"), "295386899645727233")
  }
}

Here is the GQL schema:

type OrgMember @collection(
  name: "OrgMembers"
){
  createdAt: Time!

  org: Org! @relation(
    name: "orgMembers"
  )

  user: User! @relation(
    name: "memberOfOrgs"
  )
  role: OrgMemberRole!
}

I believe it should be specified in the GQL schema somehow? Any hint?

You cannot specify compound indexes in GraphQL. But you can do it with FQL, either in the shell, web shell or your favorite driver. It will still be enforced when performing GraphQL queries.

The uniqueness of an index is the combination of all terms AND values.

For example, any of the following will enforce the user:org uniqueness

CreateIndex(
  source: Collection("OrgMembers"),
  unique: true,
  terms: [
    { field: ["data", "org"] },
    { field: ["data", "user"] },
  ]
  // no values
)

// OR

CreateIndex(
  source: Collection("OrgMembers"),
  unique: true,
  // no terms
  values: [
    { field: ["data", "org"] },
    { field: ["data", "user"] },
  ]
)

// OR

CreateIndex(
  source: Collection("OrgMembers"),
  unique: true,
  terms: [
    { field: ["data", "org"] },
  ],
  values: [
    { field: ["data", "user"] },
  ]
)
1 Like

By default, the Fauna GraphQL automatically generates the following index:

{
  name: "orgMembers",
  unique: false,
  serialized: true,
  source: "OrgMembers"
}

I’m not keen on changing it, so I’m thinking about rather create a dedicated unique index for this, in addition to what’s automatically generated, such as:

CreateIndex(
  source: Collection("OrgMembersUnique"),
  unique: true,
  terms: [
    { field: ["data", "org"] },
    { field: ["data", "user"] },
  ]
)

Does that sound like the right way to go? I do think it’s a clean way.

It’s not possible to mutate an index once created (except for it’s data field).

So making a new one is the way to go!

1 Like