Is it possible to update duplicated records in Firestore using a cloud function when there are changes made to the document

In my Firestore setup, I have the following structure:

  • Users / uid / following / followingPersonUid /
  • Users / uid / followers / followerPersonUid /

When User A follows User B, User A is added to the followers sub-collection of User B and User B is added to the following sub-collection of User A.

However, if User A updates his profile information (name, photo, username, etc.), his user document changes. This change needs to be reflected in all the places where he is a follower in other users' Followers sub-collections, such as User B or E & F.

Is it possible to achieve this using cloud functions? I have created an onCreate() trigger for cloud functions, but the function does not know the list of other users' uids where User A is a follower, making it difficult to apply the necessary update.

Shown below is the code snippet from Firebase CLI, which includes the .onUpdate() trigger for Firestore. The issue arises when trying to identify other documents in Firestore that require updating with the updated user information.

export const onUserDocUpdate = functions.region('asia-east2').firestore.document
('Users/{userId}').onUpdate((change, context) => {
const upDatedUserData = change.after.data()

const newName = upDatedUserData?.name
const profilePhotoChosen = upDatedUserData?.profilePhotoChosen
const updatersUserId = upDatedUserData?.uid
const newUserName = upDatedUserData?.userName

//Struggling here to find other documents in firestore that need 
//updating with the latest user information
    return admin.firestore()
    .collection('Users').doc('{followeeUserId}')
    .collection('Followers').doc(updatersUserId)
    .set({
    name: newName, 
    userName: newUserName,
    profilePhotoChosen: profilePhotoChosen,
    uid: updatersUserId
  })

})

Would it be better to use a callable function instead where the client can send a list of following userIds that need to be updated?

Answer №1

From my understanding, when a user updates their profile, you are looking to update that information in all of their follower's data as well. Given that you store both followers and followees, you should be able to access the subcollection of the user who triggered the cloud function:

export const onUserDocUpdate = functions.region('us-central1').firestore.document
('Users/{userId}').onUpdate((change, context) => {
  const updatedUserData = change.after.data()

  const newName = updatedUserData?.name
  const profilePhotoChosen = updatedUserData?.profilePhotoChosen
  const updatersUserId = updatedUserData?.uid
  const newUserName = updatedUserData?.userName

  const userDocument = change.after.ref.parent; // accessing the user doc that initiated the function
  const followerCollection = userDocument.collection("Followers");

  return followerCollection.get().then((querySnapshot) => {
    const promises = querySnapshot.documents.map((doc) => {
      const followerUID = doc.id;
      return admin.firestore()
        .collection('Users').doc(followerUID)
        .collection('Followees').doc(updatersUserId)
        .set({
          name: newName,
          userName: newUserName,
          profilePhotoChosen: profilePhotoChosen,
          uid: updatersUserId
        })
    });
    return Promise.all(promises);
  });
})

There might be some typos or syntax errors present, but the overall logic should be sound. The main uncertainty was regarding the follower/followee relationship structure you have in place, so I made assumptions based on what seemed logical to me.

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

Issue with Angular 2 Observable not triggering the complete function

I've been experimenting with the hero app tutorial for Angular 2 and currently have this Component set up: import { Component, OnInit } from '@angular/core' import { Subject } from 'rxjs/Subject'; import { Hero } from "./hero"; im ...

Similar to TypeScript's `hasOwnProperty` counterpart

When working with TypeScript objects, is there a way to loop through a dictionary and set properties of another dictionary similar to how it is done in JavaScript? for (let key in dict) { if (obj.hasOwnProperty(key)) { obj[key] = dict[key]; } } If ...

Having difficulty transferring navigation props between screens using react-navigation

Within my ContactList component, I have utilized a map to render various items. Each item includes a thumbnail and the desired functionality is that upon clicking on the thumbnail, the user should be directed to a new screen referred to as UserDetailsScree ...

Is it possible to associate a generic TypeScript type with another type by utilizing its generic parameters?

I am faced with a situation where I have a family of APIs consisting of various related generic types (along with associated constraints). To illustrate this, I have crafted an example using familiar types as placeholders for better understanding. As I wo ...

Accessing properties for objects with map-like characteristics

Many interfaces allow for arbitrary data, as shown below: interface Something { name: string; data: { [key: string]: any }; } The problem arises when trying to access or set values on objects with arbitrary keys in Typescript. let a: Something = { ...

The correct way to update component state when handling an onChange event in React using Typescript

How can I update the state for 'selectedValues' in a React component called CheckboxWindow when the onChange() function is triggered by clicking on a checkbox? export const CheckboxWindow: React.FC<Props> = props => { const [selected ...

Is it possible to swap out the Firestore module `doc` with the `document` module

I enjoy using the Firebase version 9 modules, however, I find that doc is not to my liking. It would be better if it were document, similar to how collection is not shortened to col. The following code does not function as expected: import { doc, collecti ...

Attempting to simulate the behavior of nfcManager by utilizing the nfcManager.start() function in react native testing library

In the process of developing my Android app, I encountered a need to read NFC tags. To accomplish this task, I decided to utilize the react-native-nfc-manager library. However, during my implementation, I faced two perplexing issues that have left me stump ...

Is it feasible to use a component in a recursively manner?

Following a two-hour search for a solution, I decided to reach out to experts as I suspected the answer might be simpler than expected. The project in question is an Angular7 one. In my goals component, I aim to include a "goal" with a button labeled "+". ...

What are some alternatives for integrating React production build files apart from utilizing Express?

Is there a way to integrate React into my library using the HTTP module? I'm trying to figure out how to recursively send static files. Specifically, I want to include the build folder from the React production build, but I'm not sure how to go a ...

What is the correct way to implement fetch in a React/Redux/TS application?

Currently, I am developing an application using React, Redux, and TypeScript. I have encountered an issue with Promises and TypeScript. Can you assist me in type-defining functions/Promises? An API call returns a list of post IDs like [1, 2, ..., 1000]. I ...

Structural directive fails to trigger event emission to parent component

Following up on the question posed here: Emit event from Directive to Parent element: Angular2 It appears that when a structural directive emits an event, the parent component does not receive it. @Directive({ selector: '[appWidget]' }) export ...

What is the best way to get both the id and name of a selected item in Angular?

Within my select field, data is dynamically populated based on names. My objective is to not only capture the selected name but also its corresponding ID. Here's a snippet of my HTML template: <select class="custom-select d-block w-100" id="test" ...

Modifying the values of various data types within a function

Is there a more refined approach to enhancing updateWidget() in order to address the warning in the else scenario? type Widget = { name: string; quantity: number; properties: Record<string,any> } const widget: Widget = { name: " ...

Sending POST request to Firestore REST API using ESP8266

I am attempting to store data in Cloud Firestore from an ESP8266. I have made adjustments to a sample code to achieve this. When I used a GET request, it worked fine and retrieved the previously saved document. However, when trying a POST request, I enco ...

Every time I attempt to destructure the state object in react typescript, I encounter the error message stating 'Object is possibly undefined'

Whenever I attempt to destructure my state object in react typescript, I encounter an error stating Object is possibly 'undefined'. When I try using optional chaining, a different error pops up saying const newUser: NewUser | undefined Argument o ...

"Encountering a blank page in React Router when transitioning between separate projects

I've come across some discussions about a similar issue like this one, but I haven't been able to resolve my problem. In my initial project, I can smoothly navigate between its pages. However, when I created a second project hosted in a subdirec ...

Inversify is a proven method for effectively injecting dependencies into a multitude of domain classes

Struggling to navigate dependencies and injections in a TypeScript-built rest web service without relying heavily on inversify for my domain classes, in line with the dependency inversion principle. Here's an overview of the project structure: core/ ...

Pause until the user selects either the confirm or deny option before proceeding with the next action

As a beginner in Angular, I am seeking help with my code structure. I have three files: WarningComponent (which displays a warning modal using Bootstrap), modalService (responsible for opening modals), and votingComponent. Within the votingComponent, ther ...

Tips for creating a simulated asynchronous queue with blocking functionality in JavaScript or TypeScript

How about this for a paradox: I'm looking to develop an asynchronous blocking queue in JavaScript/TypeScript (or any other language if Typescript is not feasible). Essentially, I want to create something similar to Java's BlockingQueue, but inste ...