Combine a main document with a document located within its sub-collection

I am managing a database within firestore that has the following structure:

-> Chat Room -> Users

Within the "ChatRoom" collection, there is a "Users" collection. Each document in the users collection includes a field "read: true/false" to track whether the user has read the messages in the room.

To fetch the rooms specific to the current user, I utilize the following code:

getRoomFromUserId(userId: string) {
    let rooms$: Observable<any>;
    let rooms: AngularFirestoreCollection<any>;

    rooms = this.afs.collection('ChatRoom', ref => {
      return ref.where('Chatter.' + userId, '==', true);
    });

    rooms$ = rooms.snapshotChanges().map(changes => {
      return changes.map(a => {
        const data = a.payload.doc.data();
        const id = a.payload.doc.id;
        return {id, ...data};
      });
    });

    return rooms$;
 }

To access data from the "Users" subcollection, I use the following line of code:

this.afs.collection('ChatRoom').doc(RoomID).collection('Users').doc(UserId);

I am keen on retrieving an object that combines the room data and the "read: true/false" status for each room. I believe it is achievable with observables, but I am uncertain about the implementation. Any suggestions on a potential solution would be highly appreciated.

Answer №1

After much deliberation, I have finally cracked the code. By utilizing the mergeMap operator in conjunction with the combineLatest operator, I was able to establish a connection between the users' sub-collections and the room document. This ingenious setup allows me to determine whether the user in question has read the messages in the room.

   Let me share with you the snippet of code where the magic happens:

    let rooms: AngularFirestoreCollection<any>;

    rooms = this.afs.collection('ChatRoom', ref => {
      return ref.where('Chatter.' + userId, '==', true);
    });

    let readRoom$: Observable<any>;
    let readRoom: AngularFirestoreCollection<any>;

    return rooms.snapshotChanges().pipe(
      mergeMap(changes => {
        return Observable.combineLatest(changes.map(a => {
          const data = a.payload.doc.data();
          const id = a.payload.doc.id;
          let roomReturn = {id, readMessage: '', photoProfile: '', ...data};

          readRoom = this.afs.collection('ChatRoom').doc(id).collection('Users');
          readRoom$ = readRoom.snapshotChanges();

          return readRoom$.pipe(
            map(userInRoom => {
              userInRoom.map(userList => {
                if (userList.payload.doc.id === userId) {
                  roomReturn.readMessage = userList.payload.doc.data().ReadMessage;
                } else {
                  roomReturn.photoProfile = userList.payload.doc.data().PhotoProfile;
                }
              });

              return roomReturn;
            })
          );
        })
        );
      })
    );

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

Unlocking the secret to accessing keys from an unidentified data type in TypeScript

The code snippet above will not compile due to an error with the email protection link. const foo: unknown = {bar: 'baz'} if (foo && typeof foo === 'object' && 'bar' in foo) { console.log(foo.bar) } An erro ...

Make the switch from TypeScript namespaces to ES2015 modules

After making adjustments to my TypeScript configuration, I am now encountering errors related to the no-namespace rule. Here is how my current setup involving namespaces looks like: Exporting classes within a namespace: namespace MyNamespace { export ...

TS2339 Error: The property does not exist on this particular type when referencing a file relatively

Currently, I am in the process of developing my own UMD library using typescript and webpack. However, I encountered an issue when importing a file that resulted in the error TS2339 (Property 'makeRequest' does not exist on type 'typeof Util ...

How can I limit a type parameter to only be a specific subset of another type in TypeScript?

In my app, I define a type that includes all the services available, as shown below: type Services = { service0: () => string; service1: () => string; } Now, I want to create a function that can accept a type which is a subset of the Service ...

core.js encountered an error at line 6237: Unable to assign value to property 'area' as it is undefined

HTML: I have created a form but encounter an error when clicking the submit button. Can someone please assist me in identifying the issue? <h3 class="page-header">Operator Form</h3> <div class="outer-container"> <form class="form-s ...

Using TypeScript to extract types from properties with specific types

My current challenge involves working with a filter object derived from an OpenAPI spec. The structure of this object is illustrated below: export interface Filters { field1: string[] field2: string[] field3: boolean field4: number } My goal is to ...

Saving an array object to a file in JSON formatting

In the midst of my work on an Angular project, I have successfully compiled data into an array and am able to download it as a CSV file using an Angular package. However, I have not been able to locate a suitable package that allows me to download the sa ...

A detailed guide on preserving session in Angular 4: a step-by-step approach

I am a beginner with Angular 4 and I'm unsure of how to implement session functionality. Can someone please explain the step-by-step process of implementing this feature in Angular 4, including where to write the necessary code? Below is an example co ...

What is the best way to retrieve the most recent entry in a Firebase real-time database?

Utilizing Firebase's real-time database, I am updating values in a chart as they change. However, my struggle lies in retrieving only the most recent value added to the database. While browsing through limitToLast and 'child_added' do not w ...

What is the correct way to convert a non-observable into an observable?

Can I convert a non-observable into an observable to receive direct image updates without having to refresh the page, but encountering this error: Type 'EntityImage[]' is missing the following properties from type 'Observable<EntityImage ...

How do I retrieve a specific svg element in Angular among multiple elements?

I recently delved into learning Angular for a new project. One of my main objectives was finding a way to dynamically alter the styles of SVG elements. This led me to utilizing ViewChild and ElementRef. Here is an example from the HTML: <svg><g ...

Exploring Attack on Titan alongside the concept of dynamic route templates in coding

I am currently working on creating a factory for an UrlMatcher. export const dummyMatcher: UrlMatcher = matchUrlFn(sitemap as any, 'dummy'); export const routes: Routes = [ { matcher: dummyMatcher, component: DummyComponent }, { path: &apos ...

I keep encountering the issue where nothing seems to be accessible

I encountered an error while working on a project using React and Typescript. The error message reads: "export 'useTableProps' (reexported as 'useTableProps') was not found in './useTable' (possible exports: useTable)". It ...

Visibility of an Angular 2 directive

It's frustrating that I can't change the visibility of a reusable directive in Angular2. 1) Let's say I have a login page. I want to control the visibility of my navbar based on whether I am on the login page or logged in. It should be hid ...

Creating an Angular material modal that uses a component wrapper and takes a component as a parameter

Currently, I am in the process of developing a dialog service that will showcase a wrapper component whose parameter is a component to be displayed as the content of the wrapper. open(component: any | TemplateRef<any>, params, viewMode: ViewMode = V ...

I am encountering a TypeScript error with URLSearchParams. The object cannot be successfully converted to a string using the toString() method

During the development of my react app with postgres, express, node, and typescript, I ran into an issue while working on the backend code. The problem arises when trying to utilize URLSearchParams. index.js import express from 'express'; import ...

I successfully installed the Firebase tools using npm, but encountered an error during the process

Alert: Please choose at least one feature. Press SPACEBAR to select features, or mention a feature by executing firebase init [feature_name] ...

Experiencing an issue with mui/material grid causing errors

An error occurred in the file Grid2.js within node_modules/@mui/material/Unstable_Grid2. The export 'createGrid' (imported as 'createGrid2') could not be found in '@mui/system/Unstable_Grid' as the module has no exports. Desp ...

The Material Table in Angular is having issues with sorting functionality

I tried implementing the basic example from the angular material website, which displays a table with accurate data but the sorting functionality is not working as expected. For reference, you can view the StackBlitz demo here: https://stackblitz.com/edit ...

TypeScript observable variable not defined

Recently, I encountered an issue and made a change to resolve it. However, I am unsure if it is the correct approach... In my project, I have defined an interface: export interface ContextEnvironment { language: string; pingUrl: string; sessionFini ...