简体   繁体   English

从 Firestore 查询数据作为可观察的

[英]Querying data from Firestore as observable

I am using this request to get my documents from Firestore asynchronously.我正在使用此请求从 Firestore 异步获取我的文档。

During an operation (delete for example) the list of my documents is not updated automatically.在操作(例如删除)期间,我的文档列表不会自动更新。 How can I transform my asynchronous function into an observable in order to take advantage of the real-time functionalities of Firestore and get the id of the document ?如何将我的异步 function 转换为可观察对象,以便利用 Firestore 的实时功能并获取文档的 ID

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}));
  }

I use AngularFire 7.2.我使用 AngularFire 7.2。 Thanks for your help.谢谢你的帮助。

Get an observable for data from Firestore query从 Firestore 查询中获取数据的可观察对象

If you want an observable from Firestore, you need to return the.valueChanges() on a AngularFirestoreCollection.如果你想要一个来自 Firestore 的可观察对象,你需要在 AngularFirestoreCollection 上返回 the.valueChanges()。 Read this doc for reference: https://github.com/angular/angularfire2/blob/master/docs/firestore/querying-collections.md .阅读此文档以供参考: https://github.com/angular/angularfire2/blob/master/docs/firestore/querying-collections.md

For example:例如:

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$; 
}

Get ID of the document获取文档的 ID

If you want the ID( which is not returned in valueChanges())on your document you need to use snapshotChanges() .如果您想要文档中的 ID(未在 valueChanges() 中返回),则需要使用snapshotChanges() Sometimes it's easier to maintain the id on the user data when saving to Firestore to avoid using snapshotChanges.有时在保存到 Firestore 时维护用户数据的 ID 会更容易,以避免使用 snapshotChanges。 Also SwitchMap is helpful in this case as when a new value comes from the source (userId in this case) it will cancel its previous firestore subscription and switch into a new one with the new user id. SwitchMap在这种情况下也很有用,因为当新值来自源(在本例中为 userId)时,它将取消其先前的 firestore 订阅并切换到具有新用户 ID 的新订阅。 If for some reason you want to maintain firestore subscriptions for all userIds that come through at once, then use mergeMap instead.如果出于某种原因,您希望为一次通过的所有 userId 维护 firestore 订阅,请改用 mergeMap。 But typically you only want to be subscribed to one user's data at a time.但通常您一次只想订阅一个用户的数据。

// Query the users by a specific email and return the first User with ID added using snapshotChanges() // 通过特定的 email 查询用户并返回使用 snapshotChanges() 添加的 ID 的第一个用户

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; 
} 
}));

Note to subscribe to the changes:订阅更改的注意事项:

The user will be null until you call subscribe on this.user$:用户将是 null,直到您在 this.user$ 上调用订阅:

const queryObservable = size$.pipe(
  switchMap(size => 
    afs.collection('items', ref => ref.where('size', '==', size)).snapshotChanges()
  )
);
queryObservable.subscribe(queriedItems => {
  console.log(queriedItems);  
});

OR或者

In your html use the async pipe which handles subscribe and unsubscribe on an observable like below:在您的 html 中使用异步 pipe 来处理订阅和取消订阅,如下所示:

<div *ngIf="(user$ | async) as user">{{ user.email }}</div>

Try to avoid using the async pipe on the same observable multiple times in your html, and instead set it as a local html variable which i do above (as user) to avoid unnecessary data trips to the db.尽量避免在您的 html 中多次对同一可观察对象使用异步 pipe,而是将其设置为本地 html 变量,我在上面(作为用户)这样做以避免不必要的数据访问数据库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM