[英]Get firestore documents from array of document references
目前,我正在對 Firestore 進行一組非常復雜的查詢。
我正在嘗試一次填充一個充滿對其他文檔的引用的數組,然后讀取這些文檔並將信息放入一個數組中。
更具體地說,對於這個示例,我在一個集合中有 4 個引用。 我想獲取這些引用,然后使用這些引用,查詢 4 個文檔並用信息填充一個數組。
順序如下:對tags
子集合中的所有文檔進行查詢,由下面的 function 處理:
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,然后返回:
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;
混亂,我知道,但我認為一旦我知道正確的運營商來使用它就會更有意義。
此外, atm this 返回一個空數組。 當我使用 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>'.
感謝您的任何幫助!
使用switchMap
出錯的原因是您沒有返回 Observable。
當使用任何“ 高階映射運算符”(switchMap、concatMap、mergeMap 等)時,提供的 function 必須返回一個 observable。 正如錯誤所述:“類型void
不可分配給類型ObservableInput<any>
”,您沒有返回任何內容(void)。
下一件不太正確的事情是,在您的循環中,您引用ref.snapshotChanges().pipe()
,但您從未訂閱它。 如您所知,可觀察對象是惰性的,除非有訂閱者,否則不會觸發。
只要你在switchMap()
中返回一個 observable,它就會自動訂閱它並發出它的值。
讓我們換個角度想一想; 而不是循環第一次調用的結果,執行它們,然后將值推送到數組中。 我們可以取而代之,將結果轉換為可觀察的 stream,它會發出它們各自調用的所有結果,並將它們組合成一個數組供您使用。 但是......有一個細微的區別:我建議不要在 stream 之外有一個單獨的tagData
數組,而是讓你的 observable 返回你需要的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], [])
})
);
讓我們打破它!
現在,您可以簡單地執行以下操作: tagData$.subscribe()
並對生成的數據數組執行您想要的操作。 或者你甚至可以在你的模板中使用異步 pipe而不是在你的組件中訂閱。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.