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

What is the significance of default parameters in a JavaScript IIFE within a TypeScript module?

If I were to create a basic TypeScript module called test, it would appear as follows: module test { export class MyTest { name = "hello"; } } The resulting JavaScript generates an IIFE structured like this: var test; (function (test) { ...

Encountering an ExpressionChangedAfterItHasBeenCheckedError in Angular 6 when selecting an option from a dropdown menu

How can we fix the error mentioned below through code changes? Situation An input dropdown UI is safeguarded against unintentional value changes by a modal. However, triggering an event (such as click or focus) on the dropdown leads to the ExpressionChan ...

Learn the process of adjusting the Time Zone in Angular2-HighCharts!

I've been struggling for a few days now trying to adjust the UTC time in an area chart using Angular2-HighCharts. The backend API is returning timestamps which I then inject into the chart, but each time it's being converted to "human time" with ...

Monitoring User Interactions for Maintaining Session Foresight Plan utilizing RxJS

My goal is to maintain user session activity by implementing a system that locks an interactive session after 15 minutes of user inactivity (defined as no keyboard or mouse activity). The information system will automatically lock the session if there is ...

Implement a call feature using ReactJS

My service method involves making a PUT call to an API with an ID parameter. However, I am facing issues with hitting the .put URL. Can someone please verify if this is the correct approach? ENDPOINTS = { SAMPLE: "/sample", }; Below is my ...

Error encountered when transitioning to TypeScript: Unable to resolve '@/styles/globals.css'

While experimenting with the boilerplate template, I encountered an unusual issue when attempting to use TypeScript with the default NextJS configuration. The problem arose when changing the file extension from .js to .tsx / .tsx. Various versions of NextJ ...

Encountering a 404 error while trying to deploy a React app on Verc

After deploying my React project with TypeScript using Vite, everything is working smoothly. However, I am encountering a 404 error when trying to refresh the page. Error: 404 NOT_FOUND Error Code: NOT_FOUND ...

Error when compiling with Component Lab's Autocomplete function for SVG Icons in Material UI

Upon running my project on the browser, I encountered the following error: Error message: ./node_modules/@material-ui/lab/esm/internal/svg-icons/Close.js Attempted import error: 'createSvgIcon' is not exported from '@material-ui/core/utils ...

How to anticipate an error being thrown by an observable in RxJS

Within my TypeScript application, there exists a method that produces an rxjs Observable. Under certain conditions, this method may use the throwError function: import { throwError } from 'rxjs'; // ... getSomeData(inputValue): Observable<s ...

"Enhance your Vue 3 projects with a dynamic library featuring universal components and full

Currently, I am in the process of developing a Vue 3 component library using Vue 3, Vite, and TypeScript. The unique aspect about this library is that it installs as a plugin and registers all components as global entities. Here is an overview of how this ...

What advantages does subscribe() offer compared to map() in Angular?

I recently started exploring observables in angular2 and found myself puzzled over the decision to use map() instead of subscribe(). Let's say I am fetching data from a webApi, like so: this.http.get('http://172.17.40.41:8089/api/Master/GetAll ...

Mastering the nesting of keys in Typescript.Unlock the secrets of

I encountered a situation where the following code snippet was causing an issue: class Transform<T> { constructor(private value: T) {} } class Test<T extends object> { constructor(private a: T) {} transform(): { [K in keyof T]: Transfo ...

Validation error from Express-validator may result in TypeScript error: the request.query object could potentially be undefined

Recently, as I was developing a Node.js app using express, I decided to enhance it with express-validator. Despite being new to express-validator, the warnings it generated perplexed me due to its lack of detailed documentation. To illustrate my point, he ...

Issue with Datatables not loading on page reload within an Angular 7 application

Incorporating jQuery.dataTables into my Angular 7 project was a success. I installed all the necessary node modules, configured them accordingly, and added the required files to the angular.json file. Everything functioned perfectly after the initial launc ...

Testing the NestJS service with a real database comparison

I'm looking to test my Nest service using a real database, rather than just a mock object. While I understand that most unit tests should use mocks, there are times when testing against the actual database is more appropriate. After scouring through ...

The modal popup will be triggered by various button clicks, each displaying slightly different data within the popup

As a newcomer to Angular 4, I have encountered an interesting challenge. Currently, my code consists of two separate components for two different modals triggered by two different button clicks (Add User and Edit User). However, I now face the requiremen ...

Accepting undefined in rest parameter of typescript

I'm struggling with an exercise involving Function parameters: The maximum function below has the wrong type. To allow undefined in the rest arguments, you need to update the type of the rest parameter. Fortunately, you don't have to change the ...

Angular2 and ReactiveX: Innovative Pagination Strategies

Currently, I am diving into the world of ReactiveX. To make things easier to understand, I have removed error checking, logging, and other unnecessary bits. One of my services returns a collection of objects in JSON format: getPanels() { return this. ...

Display fresh information that has been fetched via an HTTP request in Angular

Recently, I encountered an issue where data from a nested array in a data response was not displaying properly in my component's view. Despite successfully pushing the data into the object programmatically and confirming that the for loop added the it ...

If you're setting up a new Next.js and Tailwind CSS application, you can use the flags -e or --example to start the project as a

After several attempts at creating a Next.js app with Tailwind CSS using JavaScript, I keep getting TypeScript files. How can I prevent this error? Despite following the usual commands for setting up a Next.js project, I am consistently ending up with Typ ...