Utilizing Firebase Cloud Functions to perform querying operations on a collection

Imagine having two main collections: one for users and another for stories. Whenever a user document is updated (specifically the values username or photoUrl), you want to mirror those changes on corresponding documents in the story collection.

A sample user document might resemble this (simplified):

{
    username: 'blubber',
    photoUrl: 'my/photo/path',
    uid: 'usersUniqueId'
}

This would be an example of a story document (simplified):

{
    username: 'blubber',
    photoUrl: 'my/photo/path',
    uid: 'usersUniqueId',
    sid: 'storiesUniqueId,
    content: '...'
}

When it comes to cloud functions, you're unsure how to retrieve all story documents that match the user's id. The current code snippet looks like this:

export const onUpdateUser = functions.firestore.document('/users/{userId}')
    .onUpdate((change, context) => {
    const before = change.before.data();
    const after = change.after.data();

    if(before.username !== after.username || before.photoURL !== after.photoURL) {
        return admin.firestore().collection('/stories/')
               .where(before.uid, '==', ***fetch the comparison***)
        // perform specific action
    } else {
        return null;
    }
});

Any assistance regarding this matter would be greatly appreciated.

Answer №1

Recently made some adjustments to the code provided below. It was almost there, but I decided to incorporate async await for better code readability. Adding error handling is also recommended for a more robust implementation.

const onUpdateUser = functions.firestore.document('/users/{userId}')
    .onUpdate(async (change, context) => {
    const previousData = change.before.data();
    const newData = change.after.data();

    if (previousData.username !== newData.username || previousData.photoURL !== newData.photoURL) {
        return admin.firestore().collection('/stories/')
           .where('uid', '==', previousData.uid).get().then(  
               result => {
                   if (result.size > 0) {
                       result.forEach(async doc => {
                           await doc.ref.update({
                               username: newData.username,
                               photoUrl: newData.photoUrl
                           })
                        })
                   }
                   return;
               }
           )
    } else {
        return null;
    }
});

Answer №2

It seems like this is the goal you are aiming for.

In order to achieve that, I have restructured the function call and its reference within the .onUpdate method. Assuming your intention is to update multiple documents in the stories collection, I have implemented the use of batch.

const onUpdateUser = functions
  .firestore
  .document('/users/{userID}')
  .onUpdate(myFunc);

const myFunc = (change, context) => {
  const before = change.before.data();
  const after = change.after.data();

  // Checking if username and photoURL have changed
  if (before.username === after.username
    && before.photoURL === after.photoURL) {
    return Promise.resolve(); // Exit cloud function early if nothing has changed
  }

  return admin
    .firestore()
    .collection('stories')
    .where('uid', '==', before.uid)
    .get()
    .then((docs) => {
      const batch = admin.firestore().batch();

      docs.forEach((doc) => {
        batch.set(doc.ref, {
          username: after.username,
          photoURL: after.photoURL,
        }, {
            merge: true, // Merge fields instead of replacing entire document data
        });
      });

      return batch.commit();
    })
    .catch(console.error);
};

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

Error message: Unable to access property 'post' from undefined - Angular 2

Here is the snippet of code in my component file: import { Component, Injectable, Inject, OnInit, OnDestroy, EventEmitter, Output } from '@angular/core'; import { Http, Response, Headers, RequestOptions } from '@angular/http'; import & ...

Is it possible to get intellisense for Javascript in Visual Studio Code even without using typings?

Is it possible to have intellisense support in Visual Studio Code for a 3rd party library installed via npm, even if there is no typings file available? I have noticed this feature working in IntelliJ/Webstorm, so I believe it might be feasible. However, ...

Adjust the color of the icon depending on the value

I am new to Angular2 and I'm looking for a way to dynamically change the CSS of an icon based on specific values. Here is the code in HTML: <li><i class="fa fa-check" [style.color]="'switch(types)'"></i>{{ types }}</l ...

How can we transfer or exclude all boolean properties from one class to another or a "type"?

Within my Nestjs application, there is an entity class structured like this: @ObjectType() export class Companies { @Field(() => Int) @PrimaryGeneratedColumn({ type: 'int', name: 'id' }) public id: number; @Field() @Column ...

How to Connect to Printer in Ionic 2

Does anyone know if there is an option to implement printing/connecting a printer from Ionic 2? Is there a Cordova plugin available for printing? I found this plugin: Cordova Print plugin Any help/information on this would be greatly appreciated. Also, i ...

Modify the BehaviorSubject upon clicking or focusing on the input

I have created a directive for an input field. I want to trigger a flag in another component when the input is clicked or focused upon. @Directive({ selector: '[appDatepicker]' }) export class DatepickerDirective implements DoCheck{ constru ...

Node appears to be struggling to find the cors

I added the cors package and confirmed that it's inside the node_modules directory. However, I keep encountering this error message. /usr/src/app/node_modules/ts-node/src/index.ts:859 server | return new TSError(diagnosticText, diagnosticCodes, ...

Create a TypeScript array of objects that mirrors a Java List<Map<String, String>>

In my Java function, the argument type is List<Map<String, String>>. To perform a fetch call from a TypeScript file, I need to declare a variable whose type corresponds to List<Map<String, String>>. As TypeScript does not have a bu ...

Choose the property category

Is there a more efficient way to specify the type of a property in TypeScript without resorting to casting? Take a look at this example: interface Overlay { type: "modal" | "drawer" other?: number } const rec = { obj1: { ty ...

How can you vertically center an icon button in Material UI?

Looking for help with aligning elements in this code snippet: <TextField id="outlined-basic" label="22Keyword" defaultValue={"test123"} variant="outlined" /> <IconButton aria-label="delete&q ...

Customizing the placeholder text for each mat input within a formArray

I have a specific scenario in my mat-table where I need to display three rows with different placeholder text in each row's column. For example, test1, test2, and test3. What would be the most efficient way to achieve this? Code Example: <div form ...

Searching for a streamlined approach to retrieve a segment of a string

I'm currently working with JavaScript and TypeScript. Within my code, I encountered a scenario where I have a string that might contain certain tags indicating importance or urgency. Here are a couple of examples: A: "Remind me to go to the store to ...

Get the file without specifying type in request - Angular

Is it possible to download a file solely through the response without specifying a responsetype in the header? I am looking for a way to download the file without including any additional parameters in the header. ...

Generate a JavaScript File/Blob from an image's URI

Can I generate a File or Blob object from an image URI? I am utilizing the Cordova Image Picker plugin in my mobile application to retrieve photo URIs like this: "file:///data/user/0/..../image.jpg" However, I am struggling to create a File or Blob objec ...

Error code TS1005: Compiling Typescript DefinitelyTyped assets encountered an issue

I'm confident in my setup, but I can't seem to get tsc to compile. Here's the branch of my repository: https://github.com/inosion/sample-atom-typescript-package/tree/add_react Although I have the latest versions of typescript, I'm uns ...

Navigating SSL certificate prompts in Protractor

Our programs utilize SSL certificates and we are unable to bypass Chrome's prompt for selecting a certificate. We would be satisfied with simply choosing the one certificate needed. Attempts have been made using this code: capabilities: { browser ...

Achieving a clean/reset for a fetch using SSR in Next 13

Is there a way to update the user variable in the validateToken fetch if a user signs out later on, such as within a nested component like Navigation? What is the best approach to handle clearing or setting the user variable? Snippet from Layout.tsx: impo ...

extract keys and values from an array of objects

I would like assistance with removing any objects where the inspectionScheduleQuestionId is null using JS. How can we achieve this? Thank you. #data const data = [ { "id": 0, "inspectionScheduleQuestionId": 1, ...

Issue encountered while utilizing JQueryUI alongside TypeScript and the definition file from DefinitelyTyped

Currently, I'm attempting to incorporate JQueryUI with TypeScript by first installing JQueryUI using npm install jquery-ui-dist, and then installing JQuery with npm install jquery. Additionally, I have included the definition files from DefinitelyType ...

Converting <reference path/> directive to ESM import: A step-by-step guide

As I embark on developing a TypeScript application, I've reached the realization that I am not a fan of using the <reference path /> triple-slash directive. Instead, I prefer utilizing import 'something'. However, every time I attempt ...