簡體   English   中英

從文檔引用數組中獲取 firestore 文檔

[英]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], [])
  })
);

讓我們打破它!

  1. 我們使用from從您的數組中創建一個 observable,它一次發出每個“引用”。

  2. mergeMap將訂閱我們正在創建的 observable 並發出它的發射

  3. map只是將值轉換為您想要的形狀

  4. scan會為您累積排放量,並在每次更改時排放量。 如果您不想在所有調用返回之前發出,請改用reduce()

現在,您可以簡單地執行以下操作: tagData$.subscribe()並對生成的數據數組執行您想要的操作。 或者你甚至可以在你的模板中使用異步 pipe而不是在你的組件中訂閱。

暫無
暫無

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

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