目前,我正在处理一组与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获取引用数组,等待可观察对象结束,使用switchMap获取数据数组并循环遍历它; 理想情况下,订阅每个ref并添加到tagData中,然后返回结果:
let tagData;
this.pageService.getTagsOnPage(this.workspaceId, this.currentPage.id).pipe(
switchMap((data) => {
let references = data;
for (let j = 0; j < references.length; j++) {
let ref = this.afs.doc(`${references[j]}`);
ref.snapshotChanges().pipe(
map((actions) => {
const data = actions.payload.data();
tagData.push(data);
})
);
// push the data (different data var)
}
})
);
return tagData;
有点混乱,但我认为一旦我知道正确的运算符使用方法,这将变得更加清晰。
同时,目前返回一个空数组。当我使用switchMap时会出现以下错误:
Argument of type '(data: any[]) => void' is not assignable to parameter of type '(value: any[], index: number) => ObservableInput<any>'.
Type 'void' is not assignable to type 'ObservableInput<any>'.
感谢您的帮助!
combineLatest
可能是您的情况下正确的运算符。您可以将getTagsOnPage
的结果map
到this.afs.doc().snapshotChanges()
并将其传递给该运算符。 - Buczkowski