简体   繁体   English

Firebase 基于过滤器的 Firestore 查询

[英]Firebase Firestore Query based on filters

Let's say I have a collection of 2000 documents with fields id, age, location in cloud firestore.假设我在 Cloud Firestore 中收集了 2000 个文档,其中包含字段 ID、年龄、位置。

On client side(nodejs), I have 50 ids and want to perform a query on the firestore only for these 50 ids and should satisfy the conditions like age>25, location=chicago.在客户端(nodejs),我有 50 个 id,只想对这 50 个 id 在 firestore 上执行查询,并且应该满足 age>25,location=chicago 等条件。 I don't want to read all 50 documents.我不想阅读所有 50 份文件。 Want to read the documents from these 50 ids which satisfies the conditions I mentioned (The resulting documents could be less than 50) trying to reduce read operations.想从这50个id中读取满足我说的条件的文档(结果文档可能少于50个)试图减少读取操作。 Is it possible to do this?是否有可能做到这一点? Looking at the documentation I see there is in operator but my understanding is it only supports for 10 comparison values.查看我在操作员中看到的文档,但我的理解是它只支持 10 个比较值。 Is it possible to query as per my requirement?是否可以按我的要求查询?

While creating the documents, I can adjust the documentId to be the field id if that makes the query possible.创建文档时,如果可以进行查询,我可以将 documentId 调整为字段 id。

Based on your requirement, you can still use comparison values like code below:根据您的要求,您仍然可以使用如下代码的比较值:

Firebase Web Version 8: Firebase Web 版本 8:

db.collection("users")
    .where("age", ">", "25")
    .where("location", "==", "chicago")
    .get()
    .then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch((error) => {
        console.log("Error getting documents: ", error);
    });

Firebase Web Version 9: Firebase Web 版本 9:

const q = query(collection(db, "users"), where("age", ">", "25"), where("location", "==", "chicago");

const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
  // doc.data() is never undefined for query doc snapshots
  console.log(doc.id, " => ", doc.data());
});

You can use comparison value as much as you want using these operators ( < , <= , > , >= ).您可以使用这些运算符( <<=>>= )尽可能多地使用比较值。 By using multiple where queries, it provides you a query statement with logical AND query.通过使用多个where查询,它为您提供了一个具有逻辑AND查询的查询语句。 The only limitation are for logical OR queries which on these documentation states:唯一的限制是针对这些文档中声明的逻辑OR查询:

Cloud Firestore provides limited support for logical OR queries. Cloud Firestore 对逻辑OR查询提供有限支持。 The in, and array-contains-any operators support a logical OR of up to 10 equality (==) or array-contains conditions on a single field. in 和 array-contains-any 运算符支持单个字段上最多 10 个相等 (==) 或 array-contains 条件的逻辑OR For other cases, create a separate query for each OR condition and merge the query results in your app.对于其他情况,为每个 OR 条件创建一个单独的查询并将查询结果合并到您的应用程序中。


UPDATE:更新:

If you want to query 50 documents at the same time.如果要同时查询50个文档。 You can query it using FieldPath.documentID() and "IN" query.您可以使用FieldPath.documentID()和“IN”查询来查询它。 See code below:请参阅下面的代码:

const docArray = [
// Array of Document IDs.
];

db.collection("users")
    .where(firebase.firestore.FieldPath.documentId(), 'in', docArray)
    .where("age", ">", "25")
    .where("location", "==", "chicago")
    .get()
    .then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch((error) => {
        console.log("Error getting documents: ", error);
    });

As I stated on my previous answer, this only works if the array is of less than 10 items ( Firestore limitation ).正如我在之前的回答中所述,这仅在数组少于 10 个项目( Firestore 限制)时有效。 If you need more, you'll have to either batch the IDs, into smaller arrays and perform multiple queries.如果您需要更多,则必须将 ID 批处理为更小的 arrays 并执行多个查询。 Check code I written below:检查我在下面写的代码:

// Consists of 11 values
const docArray = [
    '5fKmta1jgEiCQBZvSJ3Y',
    'BubAGhg6IZbnzU70wdPf',
    'FVEq9trqF2Hy8ROsAjeW',
    'Nhz0pF2z3zw3aBcmnpqs',
    'TYYDYyIiyhVuWp91h7OS',
    'VDDiUGKkGnwrdo8jmDpb',
    'VXnXEuNfrhUAM8UbZ2AH',
    'XukTkr4XBey3yqAvFa3d',
    'cSNI1NgHP8OEsDY66RBw',
    'eCPc9F1bpS1qXD9WGKE2',
    'eHdKQPhE7snnRjoWJzBK'
];
const chunkedArray = [];
const resArray = [];
var promises = [];

// Firestore query limit
size = 10;

for(var i = 0; i < docArray.length; i += size) {
chunkedArray.push(docArray.slice(i, i+size));
}

chunkedArray.forEach((chunked) => {
    promises.push(
        db.collection("users")
            .where(firebase.firestore.FieldPath.documentId(), 'in', chunked)
            .where("age", ">", "25")
            .where("location", "==", "chicago")
            .get()
            .then((querySnapshot) => {
                querySnapshot.forEach((doc) => {
                    resArray.push(doc.data());
                });
            })
            .catch((error) => {
                console.log("Error getting documents: ", error);
            })
    );
})

Promise.all(promises).then(() => 
    // Returns merged data from forEach
    console.log(resArray)
);

You can also simply iterate the IDs, and get() each document individually.您也可以简单地迭代 ID,并分别对每个文档进行 get()。 Look example code below:看下面的示例代码:

docArray.forEach((docId) => {
    promises.push(
        db.collection("users")
            .where(firebase.firestore.FieldPath.documentId(), '==', docId)
            // .where("age", ">", "25")
            // .where("location", "==", "chicago")
            .get()
            .then((querySnapshot) => {
                querySnapshot.forEach((doc) => {
                    resArray.push(doc.data());
                });
            })
            .catch((error) => {
                console.log("Error getting documents: ", error);
            })
    );
})

Promise.all(promises).then(() => 
    // Returns merged data from forEach
    console.log(resArray)
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM