簡體   English   中英

通過一次查詢獲取 4 個文檔的最佳方法?

[英]Best way to get 4 documents with one query?

我正在使用 Firebase 和 angularfire(最新版本)。 我的數據模型是:

VENUES {
   [venue.id] {
      name: string
   }
}

SERVICES {
   [document.id] {
      venueid: string
      name: string
      price: number
   }
}

USERS {
   [user.id] {
      name: string;
      phone: number;
   }
}

RESERVATIONS {
   [document.id] {
      uid: <--- userID from users
      serviceid: <--- id of document from services collection
      name: string;
   }
}

所以基本上我需要在我的模板中顯示所有用戶預訂:{{reservations.service.name}} {{reservations.venue.name}} 等。“主鍵”是用戶 ID。 我創建了幫助程序,以獲取單個文檔:

  doc$(path: string): Observable<any> {
    return this.afs
      .doc(path)
      .snapshotChanges()
      .pipe(
        map(doc => {
          return { id: doc.payload.id, ...doc.payload.data() };
        })
      );
  }

所以當我需要一份文件時它可以工作。 要使用參考獲取所有預訂:

const $reservations = this.afs.collection('reservations', ref => ref.where('uid', '==', userID)).valueChanges();

我使用提供的 uid 從 resevations 集合中獲取所有文檔。

幾天前我開始使用 nosql。 我對 switchmap、map、combinelatest() 做了一些研究,但我不知道如何使用它。

我的問題是:如何將所有 observables 合並為一個獲取基於 userid 的所有文檔? 我需要從 reservations 集合中獲取文檔,其中包含 userid、用戶數據和服務數據(基於 reservations.serviceid == services.document.id)

先感謝您!

順便提一句。

我嘗試使用:

    const $reservations = this.afs.collection('reservations', ref => ref.where('uid', '==', userID)).valueChanges();
    const $services = this.afs.collection('services').valueChanges();

    return combineLatest($reservations, $services).pipe(
      map(([reservations, services]) => [...reservations, ...services])
    )

但它只允許我將管道與 ref.where 結合起來(在我獲得預訂之前我不知道 serviceid)

您可以為此使用 Angularfire leftJoin(afs, joinKey, joinCollection, limit=100)函數。

const reservations$ = this.afs.collection('reservations', ref => ref.where('uid', '==', userID)).valueChanges();
const reservationsServices$ = reservations$.pipe( 
  leftJoin(afs, 'serviceid', 'services') 
)

請在此處查看詳細說明。

如果有人正在尋找加入查詢的快速解決方案,我建議使用: https ://github.com/AngularFirebase/133-firestore-joins-custom-rx-operators

在我的例子中,我使用了 leftJoinDocument。 這是代碼:


  leftJoinDocument(field, collection) {
    return source =>
      defer(() => {
        let collectionData;
        const cache = new Map();

        return source.pipe(
          switchMap(data => {
            cache.clear();

            collectionData = data as any[];

            const reads$ = [];
            let i = 0;
            for (const doc of collectionData) {
              if (!doc[field] || cache.get(doc[field])) {
                continue;
              }

              reads$.push(
                this.afs
                  .collection(collection)
                  .doc(doc[field])
                  .valueChanges()
              );
              cache.set(doc[field], i);
              i++;
            }

            return reads$.length ? combineLatest(reads$) : of([]);
          }),
          map(joins => {
            return collectionData.map((v, i) => {
              const joinIdx = cache.get(v[field]);
              return { ...v, [field]: joins[joinIdx] || null };
            });
          }),
          tap(final =>
            console.log(
              `Queried ${(final as any).length}, Joined ${cache.size} docs`
            )
          )
        );
      });

然后在我的頁面模塊中:

  getClientReservations() {
    this.reservations = this.afs.collection('reservations', ref => ref.where('uid', '==', 'MwdM8bak78eE1omf6u04KtqlE2X2'))
      .valueChanges()
      .pipe(
        this.db.leftJoinDocument('uid', 'users'),
        this.db.leftJoinDocument('serviceid', 'services'),
        this.db.leftJoinDocument('venueid', 'venue')
      );
  }

謝謝托比亞斯給我提示:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM