Remove item from nested array

An array field cannot really be mutated in place. You have to read the whole array, change it, and update the original document with the new array.

To update in place, check this post out

To remove an item, you can Filter for the opposite of what you want to remove.

Let(
  {
    reactions: Select(["data", "reactions"], Get(Var("messageRef")), false),
    type: "❤",
    author: CurrentIdentity(),
    new_reactions: Filter(
      Var("reactions"),
      Lambda(
        "reaction", 
        Not(
          And(
            Equals(Select("type", Var("reaction")), Var("type")),
            Equals(Select("author", Var("reaction")), Var("author"))
          )
        )
      )
    )
  },
  Update(
    Var("messageRef"),
    {
      data: {
        reactions: Var("new_reactions")
      }
    }
  )
)

Warning about editing arrays and nested objects

Absolutely you can! Depending on the application, it may not be very scalable, so just watch out for some things.

Due to Fauna’s transactional and serialization guarantees you will get problems if many requests to write the same document happen at the same time. That is, those requests will time out because they cannot happen simultaneously.

If there is not a large enough user base to cause race conditions for write operations, then your approach will work fine. Or for example, there may be many MANY users, but the audience for any given message is small.

On the other hand, imagine a message with a lot of viewers, and they all want to “react” at the about the same time. That could queue up dozens or hundreds or thousands or requests to write the same document. Most of those requests will fail.

Alternative using separate collection

I hope the above answered your original question. If you want to keep discussing alternate ways to managing reactions then maybe a new forum topic would be a good place to do that. I’ll say this, though:

Consider the Fwitter (Twitter + Fauna) as an example. It’s pretty dense… but I want to focus in on one thing.

In order to track Likes, there is a separate collection (fweetstats) where each Document stores the like-status and the user that performed the action. This way, “reacting” is simply creating a document. Removing that reaction is deleting the document.

Also, as an optimization, the summary of Likes is stored in the “Fweet”. This adds a lot more complexity to the “liking” process, but helps make fetching the “feed” much more efficient. This optimization also reestablishes writing the message Document for each reaction, which still has the same problem. But at least the operation is down to incrementing and decrementing a field, which is much less complex than manipulating an unbounded array.

2 Likes