为了账号安全,请及时绑定邮箱和手机立即绑定

从文档引用数组中获取 firestore 文档

从文档引用数组中获取 firestore 文档

jeck猫 2023-01-06 15:46:26

目前,我正在处理一组相当复杂的 firestore 查询。


我试图同时填充一个包含对其他文档的引用的数组,然后读取这些文档并将信息放入一个数组中。


更具体地说,对于这个例子,我在一个集合中有 4 个引用。我想获取这些引用,然后使用这些引用查询 4 个文档并用信息填充一个数组。


顺序如下:查询tags子集合中的所有文档,由以下函数处理:


getTagsOnPage(workspaceId: string, pageId: string) {

    // get all of the references in the tags sub-collection, and puts them in an array

    // get all id's, do not get data

    return this.afs

      .collection("users")

      .doc(`${auth().currentUser.uid}`)

      .collection<Workspace>("workspaces")

      .doc(`${workspaceId}`)

      .collection<Page>("pages")

      .doc(`${pageId}`)

      .collection("tags")

      .snapshotChanges()

      .pipe(

        map((actions) => {

          return actions.map((a) => {

            const ref = a.payload.doc.get("reference");

            return ref; // return an array of (id: reference) key-value pairs

          });

        })

      );

  }

这适用于执行订阅的以下代码:


this.pageService

      .getTagsOnPage(this.workspaceId, this.currentPage.id)

      .subscribe((data) => {

        temp = data;

      });

data如下,通过控制台:


(3) ["/users/ucB5cF4Pj3PWhRn10c9mvqQbS7x2/workspaces/It1…1tSnPI5GJrniY82vZL/localTags/1p5Tscwn14PyK6zRaFHX", "/users/ucB5cF4Pj3PWhRn10c9mvqQbS7x2/workspaces/It1tSnPI5GJrniY82vZL/localTags/lFKoB0jngmtnALut2QS2", "/users/ucB5cF4Pj3PWhRn10c9mvqQbS7x2/workspaces/It1tSnPI5GJrniY82vZL/localTags/r6sf2SX6v87arU2rKsD5"]

现在,执行下一组数据读取是我开始困惑的地方。


我最初的方法是尝试 for 循环(针对此数组的长度),但这将涉及迭代执行多个嵌套订阅,我认为从这个意义上讲这是不可能的。


我是 rxjs 的新手,只使用过 map 和 switchMap 运算符。在这种情况下,我想我会使用mergeMap和/或之类的东西,flatMap,但坦率地说,我不确定在这种情况下如何进行这项工作。此外,处理我需要根据我获得的 documentReferences 数组获取文档的 for 循环也会让我陷入循环。


这是我目前的实现,无处不在;我希望对我正在尝试做的事情有感觉。基本上,通过 getTagsOnPage 获取引用数组,等待 observable 结束,使用 switchMap 获取数据数组并对其进行循环;理想情况下,订阅每个 ref 并添加到 tagData

凌乱,我知道,但我认为一旦我知道正确的操作员使用它就会更有意义。


查看完整描述

1 回答

?
智慧大石

TA贡献1720条经验 获得超3个赞

使用错误的原因switchMap是因为您没有返回 Observable。


当使用任何“高阶映射运算符”(switchMap、concatMap、mergeMap 等)时,提供的函数必须返回一个可观察对象。正如错误所述:“类型void不可分配给类型ObservableInput<any>”,您没有返回任何东西(无效)。


接下来不太正确的是,在您的循环中,您引用ref.snapshotChanges().pipe()了 ,但您从不订阅它。您可能知道,可观察对象是惰性的,除非有订阅者,否则不会触发。


只要您在 中返回一个可观察对象switchMap(),它就会自动订阅它并发出它的值。


让我们换个角度思考这个问题;而不是遍历第一次调用的结果,执行它们,然后将值推入数组。相反,我们可以获取结果并将它们变成一个可观察的流,该流发出它们各自调用的所有结果,并为您将它们组合成一个数组。但是......有一个微妙的区别:我建议不要tagData在流之外有一个单独的数组,而是让你的可观察对象返回tagData你需要的形式作为Observable<TagData[]>.


我认为这样的事情对你有用:


tagData$ = this.pageService.getTagsOnPage(this.workspaceId, this.currentPage.id).pipe(

    switchMap(references => from(references)),

    mergeMap(ref => this.afs.doc(ref).snapshotChanges()),      

    map(actions => actions.payload.data()),

    scan((allTagData, tagData) => [...allTagData, tagData], [])

  })

);

让我们分解一下!

  1. 我们用来from从您的数组中创建一个可观察对象,它一次发出每个“引用”。

  2. mergeMap将订阅我们正在创建的可观察对象并发出它的排放量

  3. map只需将值转换为您想要的形状

  4. scan为您累积排放量并在每次更改时排放。如果您不想在所有呼叫返回之前发出信号,请reduce()改用

现在,您可以简单地执行:tagData$.subscribe()并使用生成的数据数组执行您想要的操作。或者你甚至可以在你的模板中使用异步管道而不是在你的组件中订阅。


查看完整回答
反对 回复 2023-01-06
  • 1 回答
  • 0 关注
  • 6 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信