Firestore:多个条件 where 子句

IT技术 javascript firebase google-cloud-platform google-cloud-firestore where-clause
2021-02-01 04:11:22

例如,我为我的书籍列表设置了动态过滤器,我可以在其中设置特定的颜色、作者和类别。此过滤器可以一次设置多种颜色和多个类别。

   Book > Red, Blue > Adventure, Detective.

如何有条件地添加“where”?

  firebase
    .firestore()
    .collection("book")
    .where("category", "==", )
    .where("color", "==", )
    .where("author", "==", )

    .orderBy("date")
    .get()
    .then(querySnapshot => {...
6个回答

正如您在 API 文档中所见,collection()方法返回一个CollectionReferenceCollectionReference 扩展了Query,并且 Query 对象是不可变的。 Query.where()Query.orderBy()返回新的 Query 对象,这些对象在原始 Query(保持不变)的基础上添加操作。您将不得不编写代码来记住这些新的 Query 对象,以便您可以继续与它们链接调用。所以,你可以像这样重写你的代码:

var query = firebase.firestore().collection("book")
query = query.where(...)
query = query.where(...)
query = query.where(...)
query = query.orderBy(...)
query.get().then(...)

现在,您可以输入条件来确定要在每个阶段应用哪些过滤器。只需重新分配query每个新添加的过滤器。

if (some_condition) {
    query = query.where(...)
}
@JimmyKane 是什么afs你在使用 AngularFire 吗?如果是这样,您的所有对象都不同。AF 将所有内容都包装成自己的类型。
2021-03-20 04:11:22
这对我来说非常有用!谢谢!
2021-03-21 04:11:22
编辑:它有效,当你重新分配时query =,我错过了...... - 这对我不起作用。所有 where 调用都被简单地忽略。这对你仍然有效吗?
2021-03-26 04:11:22
需要注意的是,虽然可以通过多个不同属性的where进行查询,但仍然无法查询同一属性的多个where。以你的问题为例,查询还是没有解决办法.where("category", "==", "adventure").where("category", "==", "detective")
2021-03-27 04:11:22
@pikilon 这只是自以为是的语法。Typescript 应该允许您重新定义变量,使用let来定义它们。我知道这不是推荐的,因为它可能会由于范围问题而导致意外行为。如果你只是想避免警告,@ts-ignore那么就可以了。我想到的另一件事是推动每一个新的结果到一个数组:const queries = [firebase.firestore().collection("book")]; queries.push(queries[queries.length - 1].where(...)); queries[queries.length - 1].get().then(...)或者你可以写一个包装类......选择你的毒药;-)
2021-04-03 04:11:22

除了@Doug Stevenson 的回答。当您拥有多个时,有where必要像我的情况一样使其更具活力。

function readDocuments(collection, options = {}) {
    let {where, orderBy, limit} = options;
    let query = firebase.firestore().collection(collection);

    if (where) {
        if (where[0] instanceof Array) {
            // It's an array of array
            for (let w of where) {
                query = query.where(...w);
            }
        } else {
            query = query.where(...where);
        }

    }

    if (orderBy) {
        query = query.orderBy(...orderBy);
    }

    if (limit) {
        query = query.limit(limit);
    }

    return query
            .get()
            .then()
            .catch()
    }

// Usage
// Multiple where
let options = {where: [["category", "==", "someCategory"], ["color", "==", "red"], ["author", "==", "Sam"]], orderBy: ["date", "desc"]};

//OR
// A single where
let options = {where: ["category", "==", "someCategory"]};

let documents = readDocuments("books", options);

使用 Firebase 版本 9(2021 年 9 月更新):

您可以使用多个 where 子句过滤数据

import { query, collection, where, getDocs } from "firebase/firestore";

const q = query(
  collection(db, "products"),
  where("category", "==", "Computer"),
  where("types", "array-contains", ['Laptop', 'Lenovo', 'Intel']),
  where("price", "<=", 1000),
);

const docsSnap = await getDocs(q);
    
docsSnap.forEach((doc) => {
  console.log(doc.data());
});

例如,有一个数组看起来像这样

const conditionList = [
  {
    key: 'anyField',
    operator: '==',
    value: 'any value',
  },
  {
    key: 'anyField',
    operator: '>',
    value: 'any value',
  },
  {
    key: 'anyField',
    operator: '<',
    value: 'any value',
  },
  {
    key: 'anyField',
    operator: '==',
    value: 'any value',
  },
  {
    key: 'anyField',
    operator: '==',
    value: 'any value',
  },
]

然后你可以把你想设置查询条件的集合放入这个函数中。

function* multipleWhere(
  collection,
  conditions = [{ field: '[doc].[field name]', operator: '==', value: '[any value]' }],
) {
  const pop = conditions.pop()
  if (pop) {
    yield* multipleWhere(
      collection.where(pop.key, pop.operator, pop.value),
      conditions,
    )
  }
  yield collection
}

您将获得集合集查询的条件。

如果你使用角火,你可以reduce像这样使用

const students = [studentID, studentID2,...];

this.afs.collection('classes',
  (ref: any) => students.reduce(
    (r: any, student: any) => r.where(`students.${student}`, '==', true)
    , ref)
).valueChanges({ idField: 'id' });

这是多个标签的示例...

您可以轻松地为任何非角度框架更改此设置。

对于 OR 查询(不能使用多个 where 子句完成),请参见此处