Help with UDF for GQL resolver creating both docs in many-to-many relationship

Trying to write a UDF to create both User and Account and associate them in a many-to-many relation, and another to retrieve User's Accounts via GQL query.
(User can have many Accounts, and an Account can have many Users. But on User creation I’d like to create their initial Account.)

I can currently create the documents, but not retrieve them.

But I’m not even sure if my approach to this is correct. :grimacing:
Any guidance is appreciated.

I’ll outline the parts below:

With the following I get the collections User, Account, and account_has_users:

// GQL schema partial

type Account {
	...
	users: [User!] @relation(name: "account_has_users")
}
type User {
	username: String! @unique
	role: UserRole!
	accounts: [Account!] @relation(name: "account_has_users")
}
...
type Query {
    getUserAccounts: [Account!] @resolver(name: "get_user_accounts")
}
type Mutation {
    createUserAndAccount(input: CreateUserInput): User! @resolver(name: "create_user_and_account")
    ...
}

Fauna generates the create_user_and_account and get_user_accounts functions as well as the index account_has_users_by_user (and some others of course).

From looking at the index account_has_users_by_user I see it has a term of userID and a value of accountID.


the UDF for create_user_and_account

// the UDF for `create_user_and_account`
Query(
  Lambda(
    ["input"],
    Let(
      {
        user: Create(Collection("User"), {
          credentials: { password: Select("password", Var("input")) },
          data: {
            username: Select("username", Var("input")),
            role: Select("role", Var("input"))
          }
        }),
        account: Create(Collection("Account"), {
          data: {
            users: Select(["ref"], Var("user")),
          }
        }),
        account_has_users: Create(Collection("account_has_users"), {
          data: {
            accountID: Select(["ref"], Var("account")),
            userID: Select(["ref"], Var("user"))
          }
        })
      },
      {
        user: Var("user"),
        account: Var("account"),
        account_has_users: Var("account_has_users")
      }
    )
  )
)

the UDF for get_user_accounts

// the UDF for `get_user_accounts`
Query(
  Lambda(
    ["input", "size", "after", "before"],
    Let(
      {
        match: Match(Index("account_has_users_by_user"), Var("input")),
        page: If(
          Equals(Var("before"), null),
          If(
            Equals(Var("after"), null),
            Paginate(Var("match"), { size: Var("size") }),
            Paginate(Var("match"), { after: Var("after"), size: Var("size") })
          ),
          Paginate(Var("match"), { before: Var("before"), size: Var("size") })
        )
      },
      Map(Var("page"), Lambda("ref", Get(Var("ref"))))
    )
  )
)

//and the GQL query to `getUserAccounts`
query {
      getUserAccounts(
        input: "291200548912235010", 
				_size: 10
      ) {
			data {
        _id
      }
    after
    before
  	}
  }

The response to that query is an empty data array, but I am trying to get an array containing the ids of the accounts for the user ref passed to it.

//the response:
{
  "data": {
    "getUserAccounts": {
      "data": [],
      "after": null,
      "before": null
    }
  }
}

It’s always an empty array, even though I can see the docs created. I clearly have something bungled, but not sure if it’s just the query to retrieve ,or if the method of creating the docs and association is incorrect.

Again, any assistance in correcting this - but also in understanding - is greatly appreciated.

The input here will be a string and not ID. It would help if you converted it to a Ref explicitly.

Please try this.

Query(
  Lambda(
    ["input", "size", "after", "before"],
    Let(
      {
        inputRef: Ref(Collection('User'),Var("input")),
        match: Match(Index("account_has_users_by_user"), Var("inputRef")),
        page: If(
          Equals(Var("before"), null),
          If(
            Equals(Var("after"), null),
            Paginate(Var("match"), { size: Var("size") }),
            Paginate(Var("match"), { after: Var("after"), size: Var("size") })
          ),
          Paginate(Var("match"), { before: Var("before"), size: Var("size") })
        )
      },
      Map(Var("page"), Lambda("ref", Get(Var("ref"))))
    )
  )
)
1 Like

Jay, Thank You! That did it.

Not sure I would have ever caught that.