Most effective method for structuring firebase write operations within an update trigger routine

When it comes to updating multiple fields in a user document in Firebase, I am facing a dilemma. There are various fields that can be updated and have interactions with one another. Should I use a bunch of if statements, each triggering a write action if a condition is met, or should I opt for a single write at the end of the function for all potential changes? The latter option seems a bit cumbersome as it would require writing back the original value for unchanged fields. Is there perhaps a better approach that I am missing out on? What would be considered best practice in this scenario?

Let me illustrate what I currently have in place for updating fields individually:

export const userUpdate = functions.firestore
    .document("users/{userID}")
    .onUpdate(async (change) => {
      const beforeData = change.before.data();
      const afterData = change.after.data();

// Example: User levels up and gains more HP.
    if(beforeData.userLevel != afterData.userLevel){
      const newMaxHP = 15 + 5 * afterData.userLevel;
      change.after.ref.update({
        maxHp: newMaxHP
      })
    }

// Update user rating      
      if (beforeData.numberOfRatings != afterData.numberOfRatings) {
        const newRating = calculateRating(beforeData.userRating, beforeData.numberOfRatings, afterData.latestRating);
        change.after.ref.update({
          userRating: newRating
        })
      } 

// Replenish user funds if they drop to zero      
      if (afterData.money == 0){
        change.after.ref.update({
          money: 20
        })
      }

If I were to consolidate everything into a single write operation, each if statement would assign a value to a variable without directly updating the Firestore document. Additionally, each if statement would contain an else clause assigning the original value back to the field. Ultimately, there would be a single write at the end similar to this:

     change.after.ref.update({
        maxHp: newMaxHP,
        userRating: newRating,
        money: 20
      })

I hope that clarifies things.

[Additional question regarding updating map values]

@Dharmaraj's solution works well, but I'm encountering difficulties when applying it to update a map value. Just to clarify, I'm working with Typescript.

Prior to using @Dharmaraj's approach, my code looked like this:

admin.firestore().collection("users").doc(lastPlayerAttacker).update({
     "equipped.weapon.usesLeft": admin.firestore.FieldValue.increment(-1)
});

When implementing the update object, I tried the following method, but received the error "Object is of type 'unknown'":

const lastPlayerUpdates:{[key:string]:unknown} = {};
lastPlayerUpdates.equipped.weapon.usesLeft = admin.firestore.FieldValue.increment(-1);  
admin.firestore().collection("users").doc(lastPlayerAttacker).update(lastPlayerUpdates);

Any insights on how I can resolve this issue?

Answer №1

Whenever you invoke the update() function, you will incur a charge for 1 write operation. To optimize efficiency, it is recommended to gather all updated fields in an object and perform a single document update. Consider restructuring your code as demonstrated below:

export const userUpdate = functions.firestore
  .document("users/{userID}")
  .onUpdate(async (change) => {
    const beforeData = change.before.data();
    const afterData = change.after.data();

    const updatedData = {};

    // user levels up and gains more HP
    if (beforeData.userLevel != afterData.userLevel) {
      const newMaxHP = 15 + 5 * afterData.userLevel;
      updatedData.maxHp = newMaxHP;
    }

    // update user rating      
    if (beforeData.numberOfRatings != afterData.numberOfRatings) {
      const newRating = calculateNewRating(beforeData.userRating, beforeData.numberOfRatings, afterData.latestRating);
      updatedData.userRating = newRating;
    }

    // replenish user funds from zero      
    if (afterData.money == 0) {
      updatedData.money = 20;
    }

    await change.after.ref.update(updatedData);
    console.log("Data has been updated");
    return null;
  })

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

NodeJS file execution through a stored procedure

Everything I've come across regarding the topic revolves around using a NodeJS program to call a stored procedure. Inquiring: Is it feasible to reverse this process? Can a stored procedure be designed to call/execute a NodeJS file/program instead? I& ...

Is it possible to exclusively render meta tags as SSR on my website?

My website is fully developed using React for the frontend and NodeJs + Express for the backend. I am looking to implement dynamic OG (Opengraph) Tags for a specific route that is used by a specific component. Converting this component to SSR may be chall ...

Could not locate the <command> within the docker container causing npm script to fail with sh: 1 error

Query Whenever I execute the command npm run start:debug within a docker container, I encounter this particular error: # npm run start:debug > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6001100920504e504e50">[email ...

Retrieve all user accounts upon logging into Mean.io

There are two models in my system: User and Account. Whenever a user signs up, an account is automatically created for them, and they become the owner of that account. Here's an example: Account Information { "_id" : ObjectId("54f3391c96bfc9fb0b ...

MEAN Project - Organizational Endeavors

Can anyone share their recommended practices for developing a Single Web Page app project using the MEAN stack (MongoDB, Express, Angular and Node.js)? Our current setup involves: One repository for the Angular client-side code Another repository for th ...

Here's a unique version: "Sharing data between functions in the Express GET API within MEAN Stack"

Within my code, I have a function called hsResponse which operates as described below. When I run this function independently, I am able to see the expected body response in the console log. Now, I would like to incorporate this hsResponse function within ...

Executing commands in the package.json file

Currently navigating a sizable codebase, my aim is to execute scripts from the package.json file exemplified below: https://i.stack.imgur.com/a1Rvu.png Whenever the command "npm start" is initiated, it defaults to the dev script resulting in an ...

Troubleshooting issues with accessing the _id property using Typescript in an Angular application

Encountering an Angular error that states: src/app/components/employee/employee.component.html:67:92 - error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is ...

Allow npm to refresh the node_modules/.bin symbolic links

In the event that the top level node_modules/.bin directory has been deleted, is there a method to instruct npm to recreate the symlinks without having to delete the entire node_modules directory and perform a complete npm install again? ...

Error message from FB Messenger bot: Unable to access the property 'object' as it is undefined

I am currently testing my bot using a friend's Facebook account because I cannot locate the message option on my own Facebook page. I have been following the guidelines at https://developers.facebook.com/docs/messenger-platform/getting-started/quick-s ...

What is the reason browsers do not store JWT tokens in the same manner as they do cookies?

Understanding the distinctions between a cookie and a JSON web token is crucial. With cookies, when the server includes 'set-cookie' in its response header, the browser automatically stores the cookie in local storage. Then, whenever the cookie i ...

Activate trust proxy in Next.js

When working with Express.js, the following code snippet enables trust in proxies: // see https://expressjs.com/en/guide/behind-proxies.html app.set('trust proxy', 1); I am attempting to implement a ratelimit using an Express middleware that is ...

Collaborating on documents across microservices

I am currently in the process of transitioning a project from a monolithic structure to microservices architecture. The project is built in Node.js, and I have started exploring Seneca.js, specifically its seneca-mesh module. My first step was to move imag ...

Dealing with uncaught promise rejection while using the 'opn' npm package in Docker

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Exited with code 3 I encountered this error while trying to open links using a module within a Docker container. The code functioned fine on my local machine without D ...

Tips on utilizing React and Node to upload text as a file to Google Drive

Are you wondering how to incorporate React.js as the frontend and Node.js as the backend for uploading/reading files from Google Drive? In my attempts, I've tried writing a string as a text file and then uploading it to Google Drive by following this ...

Get specific information from Firebase based on a certain field

I am working with Firebase and the database structure I have is as follows: Users user1 email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c2a7baa3afb2aea7f382b6a7b1b6eca1adaf">[email protected]</a>" ...

Updating model names and table names with Loopback and MySQL in Node.js can easily be done by following a few

Utilize Loopback(nodejs) in conjunction with mysql. I am looking to alter the model name and table name to something different. I prefer not to display the table name in the API URL. New table name = 'super_member' New model name = 'memb ...

Encountering an internal/modules/cjs/loader.js:892 error when attempting to install the newest version of node.js on Windows 10

After recently updating my node.js to the latest version using chocolatey, I encountered a problem with my command prompt displaying the following error: internal/modules/cjs/loader.js:892 throw err; ^ Error: Cannot find module 'C:\Users&bso ...

Exploring the power of NodeJS modules through exports referencing

Encountering difficulties referencing dynamic variables related to mongoose models based on user session location value. Two scripts are involved in this process. The first script is called location.js & reporting.js In the location.js script: module.ex ...

The error message from the mongoose plugin is indicating a problem: it seems that the Schema for the model "Appointment" has not been properly registered

I need help troubleshooting a mongoose error that is being thrown. throw new mongoose.Error.MissingSchemaError(name); ^ MissingSchemaError: Schema hasn't been registered for model "Appointment". Use mongoose.model(name, schema) I have double-c ...