【问题标题】:Best way to get 4 documents with one query?一次查询获取 4 个文档的最佳方法?
【发布时间】:2020-03-23 03:41:37
【问题描述】:

我正在使用 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() 做了一些研究,但我不知道如何使用它。

我的问题是:如何根据用户 ID 将所有可观察对象合并为一个获取所有文档? 我需要从预订集合中获取用户 ID、用户数据和服务数据的文档(基于 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)

【问题讨论】:

    标签: angular typescript firebase google-cloud-firestore angularfire


    【解决方案1】:

    如果有人正在寻找加入查询的快速解决方案,我建议使用: 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')
          );
      }
    

    感谢 tobias 为我提供提示 :)

    【讨论】:

      【解决方案2】:

      您可以为此使用 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') 
      )
      

      查看详细说明here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多