Searching for a specific document using AngularFirestore - what's the best method?

Is it possible to create an Observable that is limited to a single document?

While the code provided creates an Observable for querying multiple documents:

foo.component.ts

import { AngularFirestore } from '@angular/fire/firestore';
import { Observable } from 'rxjs';

...

export class FooComponent implements OnInit {

...

    docs: Observable<any[]>;

    constructor(private db: AngularFirestore) {
        this.docs = db.collection('myCollection', ref => ref.where('name', '==', 'foobar')).valueChanges();

}

foo.component.html

<div *ngFor="let doc of docs | async">
    {{ doc.name }}, {{ doc.address }}
</div>

If I know there will only be 1 document returned, how can I achieve the same result without using an *ngFor loop?

I attempted

this.doc = db.collection('myCollection', ref => ref.where('name', '==', 'foobar').limit(1)).valueChanges();

Answer №1

Here is a functional stackblitz example: https://stackblitz.com/edit/angular-v7yff2

Building upon this https://stackblitz.com/edit/angular-lymeyp base, simply implement the following in your component:

crazinessToObserveASingleDoc() {
        this.singleDoc = this.db.collection('users', ref => ref.where('email', '==', this.email)).valueChanges().pipe(
          tap(docs => console.log('docs', docs)),
          map(val => val.length > 0 ? val[0] : null)
        )
    }

and insert this in your template:

<div>
    <span class="title">Document with email <span class="italics">{{ email }}</span>:</span>
    <div *ngIf="singleDoc | async as doc">{{ doc.name }}, {{ doc.email }}</div>
</div>

Past solution

Avoid using take(1) as suggested by some comments: it ends the observable and you won't be able to keep track of changes (defeating the purpose of using a real-time database). Furthermore, you will still get an array of results...

If you are unaware of the document ID, utilize the following approach:

const doc: Observable<any | null> = 
   db.collection('myCollection', ref => ref.where('name', '==', 'foobar'))
     .valueChanges()
     .pipe(map(val => val.length > 0 ? val[0] : null));

where the map function is from rxjs/operators.

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

Understanding NestJS Mixins and Their Distinction from Inheritance

After researching, I found that the Nestjs documentation does not include any information about mixins. Here is what I have gathered from my findings on Google and Stack Overflow: A mixin serves as a means of code sharing between classes within Nest. Esse ...

Leverage ng2-charts along with a loading component during the AfterViewInit lifecycle hook

Currently, I am working on a web page that contains various charts. My focus right now is on developing a simple loader as shown below: <div *ngIf="loading === true; else elseBlock" class="container"> <div class="grid-pulse la-3x"> </di ...

Arrangement of items in Angular 2 array

Received a JSON response structured like this JSON response "Terms": [ { "Help": "Terms", "EventType": "Success", "Srno": 1, "Heading": "Discount Condition", "T ...

Tips for retrieving Angular routing data from external sources outside of an Angular application

Is there a way to automatically generate a sitemap for each module during build time? The project structure is as follows: - cli - client -- Module A -- Routing A -- Module B -- Routing B -- Module C -- Routing C - server I am ...

Ways to improve the feedback for Typescript when dealing with the potential existence of a nested method

Recently encountered a critical bug that I believe could have been identified with the right TypeScript setup. Struggling to come up with a suitable title, so please bear with me. While initializing a widget app, similar to a chat app loaded by a parent a ...

"Creating a Typescript property that is calculated based on other existing properties

I am working on a Typescript project where I have a basic class that includes an `id` and `name` property. I would like to add a third property called `displayText` which combines the values of these two properties. In C#, I know how to achieve this using ...

Embracing the "export ... from" feature in the TypeScript compiler

Can the tsc compiler handle this particular export statement? export {PromiseWrapper, Promise, PromiseCompleter} from 'angular2/src/facade/promise'; Your assistance is greatly appreciated! ...

What is the best way to combine API calls using rxJs subscribe and map in Angular?

Currently, I am executing multiple API requests. The first one is responsible for creating a User, while the second handles Team creation. Upon creating a User, an essential piece of information called UserId is returned, which is crucial for the Team cre ...

Why does the CSHTML button containing a JavaScript onclick function only function intermittently?

I've implemented a download button on a webpage that dynamically assigns an ID based on the number of questions posted. Below is the code for the button: <input data-bind="attr: { id: $index() }" type="button" value="Downlo ...

Stuck on loading screen with Angular 2 Testing App

Currently working on creating a test app for Angular 2, but encountering an issue where my application is continuously stuck on the "Loading..." screen. Below are the various files involved: app.component.ts: import {Component} from '@angular/core& ...

Transformation occurs once you subscribe to an observable entity

Within the x.component.ts, I initiate the getSomething() method from y.service.ts. Since this method returns an observable, I subscribe to it. However, I encounter a peculiar issue where an object with 4 elements, one being an array of number arrays (numbe ...

Attempting to organize a list using Angular 8 CDK Drag and Drop functionality

Currently, I am working on creating a drag and drop list using Angular. However, I am facing an issue with resetting the tables to their initial arrangements. I attempted to utilize transferArrayItem but I am struggling to find a way to reference the table ...

Improprove the performance of an array of objects using JavaScript

Hello there, I am currently in the process of creating an array. this.data = [{ label: 'Total', count: details.request.length, }, { label: 'In-Progress', count: details.request.filter((obj) => obj.statusId === 0 || ob ...

Guide on how to run functions in Angular 2+ directly from the console?

My application is designed to operate within a chromium browser using chromiumfx. With chromiumfx, you can seamlessly run any JavaScript functions as if you were working in a console environment. Here's a snippet of my code: import { Component } f ...

Link Array Element to [(value)] within Angular

Hey there! I'm currently working with Angular Material and dealing with an Array of products to generate a table in my template. <tbody> <tr *ngFor="let item of productArray | async; let i = index"> Within this loop, I have another l ...

Having trouble retrieving files from an Angular2 service

I am facing an issue in creating an Angular2 service for downloading files from the server. I have a table where each record represents a single file. When clicking on a specific record, the download method is called: download(r: FileObject) { this.re ...

Utilizing union type return values in Typescript

Looking to incorporate shelljs (via DefinitelyTyped) into my Typescript 1.5-beta project. I want to utilize the exec function with the specified signature: export function exec(command: string, options: ExecOptions): ExecOutputReturnValue | child.ChildPro ...

Using jest-dom without Jest is definitely an interesting challenge that many developers may

Can anyone help me with extending Typescript interfaces? I have come across a situation that I am trying to solve. In my tests, I am utilizing expect without using Jest directly (I installed it separately and it functions properly). Now, I am interested ...

Ways to inform websocket client of authentication failure

Utilizing the (ws package) in Node.js to handle websockets, I leverage the "on upgrade" event to authenticate incoming clients based on a token provided as a URL parameter. Following the guide here, if the token is invalid/missing/expired, I utilize the fo ...

NavigatedRoute and Auth-protect - problem retrieving ID from paramMap

Currently working on a website for my exam project, but encountering an issue with the AuthGuard not returning the correct ID in my code. event-details.component.ts getEvent(): void { const id = +this.route.snapshot.paramMap.get('id'); ...