12

FaunaDB's documentation covers how to update a document, but their example assumes that I'll have the id to pass into Ref:

Ref(schema_ref, id)
client.query(
  q.Update(
    q.Ref(q.Collection('posts'), '192903209792046592'),
    { data: { text: "Example" },
  )
)

However, I'm wondering if it's possible to update a document without knowing its id. For instance, if I have a collection of users, can I find a user by their email, and then update their record? I've tried this, but Fauna returns a 400 (Database Ref expected, String provided):

client
  .query(
    q.Update(
      q.Match(
        q.Index("users_by_email", "me@example.com")
      ),
      { name: "Em" }
    )
  )
Em.
  • 175
  • 7

2 Answers2

13

Although Bens comments are correct, (that's the way you do it), I wanted to note that the error you are receiving is because you are missing a bracket here: "users_by_email"), "me@example.com"

The error is logical if you know that Index takes an optional database reference as second argument.

To clarify what Ben said: If you do this you'll get another error:

Update(
  Match(
    Index("accounts_by_email"), "test@test.com"
  ),
  { data: { email: "test2@test.com"} }
)

Since Match could potentially return more then one element. It returns a set of references called a SetRef. Think of setrefs as lists that are not materialized yet. If you are certain there is only one match for that e-mail (e.g. if you set a uniqueness constraint) you can materialize it using Paginate or Get: Get:

Update(
  Select(['ref'], Get(Match(
      Index("accounts_by_email"), "test@test.com"
  ))),
  { data: { email: 'test2@test.com'} }
)

The Get returns the complete document, we need to specify that we require the ref with Select(['ref']..

Paginate:

Update(
  Select(['data', 0], 
    Paginate(Match(
      Index("accounts_by_email"), "test@test.com"
    ))
  ),
  { data: { email: "testchanged@test.com"} }
)
Brecht De Rooms
  • 1,802
  • 7
  • 15
10

You are very close! Update does require a ref. You can get one via your index though. Assuming your index has a default values setting (i.e. paging a match returns a page of refs) and you are confident that the there is a single match or the first match is the one you want then you can do Select(["ref"], Get(Match(Index("users_by_email"), "me@example.com"))) to transform your set ref to a document ref. This can then be passed into update (or to any other function that wants a document ref, like Delete).

benjumanji
  • 1,395
  • 7
  • 15
  • 1
    Thanks so much to both of you! I'm accepting this as the answer because it solves my problem, although anyone else who visits this issue should also read Brecht's for more context. – Em. Mar 10 '20 at 16:42