Estoy usando esta solicitud para obtener mis documentos de Firestore de forma asíncrona.
Durante una operación (borrar por ejemplo) la lista de mis documentos no se actualiza automáticamente. ¿Cómo puedo transformar mi función asincrónica en un observable para aprovechar las funcionalidades en tiempo real de Firestore y obtener la identificación del documento ?
import { Injectable } from '@angular/core'; import { SentencePair } from '../models/sentence-pair.model'; import { Firestore, collectionData, deleteDoc,limit, limitToLast,orderBy, increment, addDoc, collection, doc, updateDoc, setDoc,query, where, getDocs } from '@angular/fire/firestore'; import { Observable,combineLatest,map, defer } from 'rxjs'; @Injectable({ providedIn: 'root'}) export class SentencesPairsService { constructor(private firestore: Firestore) { } async FilterPairs(field: string, boolean: boolean, display:any) { const sentencepairsRef = collection(this.firestore, 'SentencesPairs'); const q = query(sentencepairsRef, where('validation', '==', boolean), where('origin_trad', 'in', display), orderBy(field),limitToLast(10)); const truc = await getDocs(q) return truc.docs.map(docData=>({...docData.data(), id:docData.id})); }Yo uso AngularFire 7.2. Gracias por tu ayuda.
Obtenga un observable para los datos de la consulta de Firestore
Si desea un observable de Firestore, debe devolver .valueChanges() en AngularFirestoreCollection. Lea este documento como referencia: https://github.com/angular/angularfire2/blob/master/docs/firestore/querying-collections.md .
Por ejemplo :
getUserByEmail(email: string): Observable<User> { const collection = this.firestore.collection<User>('users', ref => ref.where('email', '==', email)) const user$ = collection .valueChanges() .pipe( map(users => { const user = users[0]; console.log(user); return user; })); return user$; }Obtener ID del documento
Si desea la ID (que no se devuelve en valueChanges()) en su documento, debe usar snapshotChanges() . A veces, es más fácil mantener la identificación en los datos del usuario cuando se guardan en Firestore para evitar usar snapshotChanges. También SwitchMap es útil en este caso, ya que cuando un nuevo valor proviene de la fuente (userId en este caso), cancelará su suscripción anterior a Firestore y cambiará a una nueva con la nueva identificación de usuario. Si, por algún motivo, desea mantener suscripciones de Firestore para todos los ID de usuario que aparecen a la vez, utilice mergeMap en su lugar. Pero, por lo general, solo desea estar suscrito a los datos de un usuario a la vez.
// Consulta a los usuarios por un correo electrónico específico y devuelve el primer usuario con ID agregado usando snapshotChanges()
return this.firestore.collection<User>('users', ref => ref.where('email', '==', email)) .snapshotChanges() .pipe(map(users => { const user = users[0]; if (user) { const data = user.payload.doc.data() as User; const id = user.payload.doc.id; return { id, ...data }; } else { return null; } }));Nota para suscribirse a los cambios:
El usuario será nulo hasta que llames a subscribe en this.user$ :
const queryObservable = size$.pipe( switchMap(size => afs.collection('items', ref => ref.where('size', '==', size)).snapshotChanges() ) ); queryObservable.subscribe(queriedItems => { console.log(queriedItems); });O
En su html, use la tubería asíncrona que maneja la suscripción y la cancelación de la suscripción en un observable como el siguiente:
<div *ngIf="(user$ | async) as user">{{ user.email }}</div>Intente evitar el uso de la tubería asíncrona en el mismo observable varias veces en su html y, en su lugar, configúrelo como una variable html local que hago arriba (como usuario) para evitar viajes de datos innecesarios a la base de datos.