Challenges encountered while retrieving data from Cloud Firestore

Here's the setup I have on my Cloud Firestore:

Collection question:
- userID
- text

and Collection user:
- name 
- key

I am able to easily retrieve the question data from the database and display it, but currently without the user data. Then, I need to perform another search in the database for each comment that was previously retrieved. However, I am encountering numerous difficulties trying to accomplish this.

First:

I start by searching for the questions:

Component:

export class ListQuestionsComponent implements OnInit {
  tableData: Question[] = [];
  userData: User[] = [];

constructor(
      private questionService: QuestionService,
      private userService: UserService,
  ) { }

 ngOnInit() {
    this.loadItems();
    this.getUsers();
  }

loadItems() {
    this.questionService.loadItems().subscribe(response => {
      this.tableData = [];
      for (const item of response) {
        this.tableData.push(item.payload.doc.data() as Question);
      }
}

Question Service:

loadItems() {
    const query = ref => ref
    .limit(10);

    return this.firestore.collection('perguntas', query).snapshotChanges();
}

This successfully fetches the questions and populates the tableData array. Now, I need to find the respective user for each of these questions.

I attempted to do this within the same Component:

getUsers() {
 for(const item of this.tableData) {
   this.userService.getUserByKey(item.userID).subscribe(response => {
      this.userData = [];
      for (const user of response) {
        this.userData.push(user.payload.doc.data() as User);
      }
   });
 }
}

User Service

getUserByKey(key: string) {
    return this.firestore.collection('users', ref => ref
      .where('key', '==', key))
      .snapshotChanges();
  }

After all this, I have a tableData with 10 questions, but userData remains empty. I am unsure of what to do next. My goal is to retrieve only the users who are associated with the questions I've fetched.

Answer №1

In my experience with Firestore, I have found it effective to store necessary data along with the main data being retrieved.

For example, if I am retrieving information about questions and know that I will also need details about the user, such as their username and profile picture, I include a user field in each question document containing the user's ID, username, and profile picture.

This structure could look like:

Questions:
---> Question
---> Date
---> User:
-------> ID
-------> Profile Picture
-------> Username

Additionally, when deciding how to handle updated user data, consider what information needs to be kept current. For critical data, such as usernames affecting routing, you can set up listeners for changes in your core user collection:

exports.updateUser = functions.firestore
    .document('user/{userId}')
    .onUpdate((change, context) => {
      const newValue = change.after.data();
      const previousValue = change.before.data();

      const newName = newValue.name;
      const oldName = previousValue.name;

      if (newName !== oldName){
          //update all questions where userId matches.
      }

      // perform other desired operations ...
    });

For more information on Cloud Functions and Firestore events, refer to the Firebase documentation: https://firebase.google.com/docs/functions/firestore-events#trigger_a_function_when_a_document_is_updated

Answer №2

After delving into the concept of asynchronous functions, I made some modifications to my code and saw positive outcomes.

The variable for user data is now declared as:

userData: any;

Within the subscription of my loadItems() function, I invoked getUsers().

The implementation of my getUsers() method looks like this:

getUsers() {    
  for (const item of this.tableData) {
    this.userService.getUserByKey(item.userId).subscribe(response => {
      this.userData[item.userId] = response[0].payload.doc.data();
    });
  }
}

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

Implement Bootstrap into Asp.Net Core 6 for the scaffolded Identity _Layout.cshtml

In my development environment using VS2022 Preview, I have set up a Single Page Application with Angular and the default project provided by VS2022. To customize the appearance of the Identity pages, I decided to override Bootstrap with a style from Bootsw ...

Creating dynamic buttons based on a list: A step-by-step guide

Is there a way to dynamically generate and display buttons based on the number of elements in a list? I currently have a hardcoded implementation, but sometimes my list only contains two elements (button 1 and button 2) so I don't need the additional ...

Exploring the possibilities of utilizing Angular 2 in conjunction with YII2

Why am I asking this question? I want to incorporate Angular2 routes on my Frontend and YII2 views on the Backend. I'm considering using AJAX page loading with Angular2 for YII2 pages... hmm... That's an interesting idea. But, is it the right a ...

The PathLocationStrategy function is designed to work exclusively within a local

I am facing a hash problem in my current project. Interestingly, everything works correctly in the test project. I have searched on Google for solutions but couldn't find any satisfactory answers: Angular2 without hash in the url When I add {provide ...

Tips for Preventing Websites from Hijacking Keyboard Shortcuts in Chrome Extension Development

Currently, I am developing a browser extension and have added an input form within a modal. However, I have encountered an issue where website shortcut key events take precedence over input key presses. As a result, I am unable to capture the input lette ...

"Fixing the cubic-bezier for the exiting animation ends up causing issues with the entering

Trying to implement a collapsing list animation using React/Joy-UI. Below is the Transition element code snippet: <Transition nodeRef={nodeRef} in={browseOpen} timeout={1000}> {(state: string) => (<List aria-labelledby="nav-list-bro ...

Styling: petite vibrant square positioned in the corner of a large container

Can you please take a look at the screenshot from the demo app: box over box image I am trying to create a colorful small square box that will appear in the top left corner, on top of the larger parent square box (including all the contents inside the whi ...

Ways to activate an Angular controller function when the internal status is altered?

What is the optimal approach for ensuring that my Angular component triggers the bound method (referred to as isItemExpended in this scenario) whenever changes occur in the internal data model? TypeScript @Component({ ... }) export class ItemsComponent ...

Angular Image Cropping: A How-To Guide

I have been on the lookout for an Angular plugin that allows me to crop images before uploading them to the database. Despite spending all day searching, I have not been able to find a suitable plugin that meets my requirements. What I need specifically i ...

How can type annotations be properly incorporated into this TypeScript code using an inline function class?

How can I provide type annotations to inform TypeScript that this code is correct? Indeed, I do require that inline function class. The code presented here is a simplified version of my actual problem. let x = 10; const obj = new (function() { if(--x) r ...

I am having difficulty accessing the values stored in my cardTiles variable

I am facing an issue with a variable called cardTiles in my Angular 9 component. The variable is defined as cardTitles:Product[] = []; The Product class is defined as follows export class Product{ productName: string;} When I console.log(this.cardTi ...

Error: Missing provider for String value

Encountering an error in the browser after adding a string parameter to the constructor of my class: https://i.sstatic.net/Hh1wM.png The structure of my class is as follows: import { Component, OnInit } from '@angular/core'; import { MatrixCo ...

Having trouble retrieving certain header values in Angular 4

Using Angular 4, I am making a back-end query like this: this.classzService.query({ page: this.page, size: this.itemsPerPage, sort: this.sort(), url: url }).subscribe( (res: Response) => this.onQuerySuccess(res.jso ...

Storing Angular 4 Http Post response data in an object

I'm currently working with Angular 4 in conjunction with an Asp.net web API. I am facing difficulties in reading the properties of my response. This is how my response appears: https://i.stack.imgur.com/NDJCo.png Here is my post request: postLogi ...

Resolving Angular Issue: Error code (5, 12) TS2314 - Solving the requirement for 1 type argument in the 'Array<T>' generic type

Encountered an issue in the JSON data within my typescript file. I'm working on creating an Angular API that performs a git-search operation. Initially, I had the JSON data set up correctly but then I modified all data values to their respective data ...

`Troubleshooting problem with debugging mocha tests in a TypeScript environment`

I'm currently facing an issue while trying to debug a mocha test. Despite my efforts in searching on Google and Stack Overflow, I have not been able to find a solution. The error message is as follows: TSError: ⨯ Unable to compile TypeScript: sour ...

What is the best way to retain all checkbox selections from a form upon submission?

I have a batch of checkboxes that correspond to the profiles I intend to store in the database. HTML: <tr *ngFor="let profile of profiles | async"> <input type='checkbox' name="profiles" value='{{profile.id}}' ng-model=&apo ...

Is it possible to divide an Observable<boolean[]> into an array of Observable<boolean>?

Within a component, I have the following code snippet: // this.can... are boolean values redux .watch(state => state.userInfo.access.current) .takeUntil(this.done) .subscribe(access => [this.canPartners, this.canServices, this.canTens, thi ...

Exploring the Differences Between Angular 2 Two-Way Data Binding and One-Way

My query pertains to the distinction between Angular 2's two-way and one-way data binding mechanisms. From my understanding, one-way data binding involves data flowing strictly from parent to child. However, this changes when the source of the binding ...

Unit tests may not properly update the Angular Async pipe

Struggling with updating Observables using the async pipe in HTML during unit tests. I want to test not only the component itself but also ensure that child components are rendered correctly with the right Inputs. Here is a simple example where the issue ...