如何获取firestore collectionGroup查询的父文档?

Mar*_*yne 4 javascript firebase google-cloud-platform google-cloud-firestore

我正在尝试获取我得到的所有子集合查询的父文档,因此我的数据库看起来像这样

/生产/id/位置/id/positionhistory

我获得了职位历史的所有文件,但我还需要一些职位和生产的数据。我希望是否有一种方法可以在 collectionGroup 查询中获取父母的文档。我也在使用 firestore v9。

const getHistory = async () => {
  setLoading(true);
  try {
    const userHisRef = query(
      collectionGroup(db, "positionhistory"),
      where("userid", "==", currentUser.uid)
    );
    const querySnapshot = await getDocs(userHisRef);
    let arr = [];
    querySnapshot.forEach((doc) => {
      console.log(doc.id);
      arr.push(doc.id);
    });

    setLoading(false);
  } catch (err) {
    console.log(err);
    setLoading(false);
    
  }
};
getHistory();
Run Code Online (Sandbox Code Playgroud)

Ren*_*nec 12

正如 Pierre Janineh 所指出的,您需要使用和类parent的属性。DocumentReferenceCollectionReference

具体来说,对于其中的每个QueryDocumentSnapshot(“提供与”相同的 API 表面DocumentSnapshot),QuerySnapshot您可以执行以下操作:

const querySnapshot = await getDocs(userHisRef);
let arr = [];
querySnapshot.forEach((doc) => {

  const docRef = doc.ref;   
  const parentCollectionRef = docRef.parent;   // CollectionReference
  const immediateParentDocumentRef = parentCollectionRef.parent; // DocumentReference
  const grandParentDocumentRef = immediateParentDocumentRef.parent.parent; // DocumentReference
  // ...
});
Run Code Online (Sandbox Code Playgroud)

因此,您可以轻松获取父母和祖父母文档的DocumentReferences(和s)。id

但是,您想要获取这些父/祖父母文档的一些数据(“我还需要一些来自位置和生产的数据”),这更复杂......因为您实际上需要根据它们的DocumentReferences查询这些文档。

为此,您可以使用Promise.all()在循环中构建的一个或多个承诺数组(如下所示),但是,根据您需要的父级数据量,您还可以对数据进行非规范化并向子级添加所需的数据来自父母和祖父母文档的数据。

要获取所有父母和祖父母文档的数据,您可以执行以下操作:

const querySnapshot = await getDocs(userHisRef);
let arr = [];

const parentsPromises = [];
const grandparentsPromises = [];

querySnapshot.forEach((doc) => {
  const docRef = doc.ref;   
  const parentCollectionRef = docRef.parent;   // CollectionReference
  const immediateParentDocumentRef = parentCollectionRef.parent; // DocumentReference
  const grandParentDocumentRef = immediateParentDocumentRef.parent.parent; // DocumentReference
  
  parentsPromises.push(getDoc(immediateParentDocumentRef));
  grandparentsPromises.push(getDoc(grandParentDocumentRef));
  // ...
});

const arrayOfParentsDocumentSnapshots = await Promise.all(parentsPromises);
const arrayOfGrandparentsDocumentSnapshots = await Promise.all(grandParentDocumentRef);
Run Code Online (Sandbox Code Playgroud)

您将得到两个 s 数组,DocumentSnapshot您可以从中获取数据。但您很可能需要将它们中的每一个与其相应的子/孙文档链接起来......

由于 with Promise.all(),返回的值将按照传递的 Promises 的顺序排列,因此您可以使用初始数组的索引(即循环 with 的顺序querySnapshotforEach,但这有点麻烦......

此外,请注意,如果子集合之一中有多个文档positionhistory,则您将多次影响相同的父文档和祖父文档。您可以维护已获取的文档 ID 的列表,但这又增加了一些复杂性。

因此,出于所有这些原因,如果对数据进行非规范化不更容易/更好,最好进行分析,如上所述。