Firestore:多个条件 where 子句

Posted

技术标签:

【中文标题】Firestore:多个条件 where 子句【英文标题】:Firestore: Multiple conditional where clauses 【发布时间】:2018-06-10 17:49:40 【问题描述】:

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

   Book > Red, Blue > Adventure, Detective.

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

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

    .orderBy("date")
    .get()
    .then(querySnapshot => ...

【问题讨论】:

【参考方案1】:

正如您在 API 文档中看到的,collection() 方法返回一个 CollectionReference。 CollectionReference 扩展了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(...)

【讨论】:

编辑:它有效,当您重新分配query = 时,我错过了... - 这对我不起作用。所有的 where 调用都被简单地忽略了。这仍然对您有用吗? @JimmyKane afs 是什么?你在使用 AngularFire 吗?如果是这样,那么您的所有对象都是不同的。 AF 将所有内容包装到自己的类型中。 需要注意的是,虽然可以查询多个不同属性的where,但仍然不能查询同一属性的多个where。以您的问题为例,查询.where("category", "==", "adventure").where("category", "==", "detective")仍然有no解决方案 @pikilon 这只是固执己见的语法。 Typescript 应该允许您重新定义变量,使用let 来定义它们。我知道不建议这样做,因为它可能由于范围问题而导致意外行为。如果您只是想避免警告,@ts-ignore 就可以了。想到的另一件事是将每个新结果推入一个数组:const queries = [firebase.firestore().collection("book")]; queries.push(queries[queries.length - 1].where(...)); queries[queries.length - 1].get().then(...)。或者你可以写一个包装类......选择你的毒药;-) 您现在可以使用 IN 运算符:firebase.google.com/docs/firestore/query-data/queries【参考方案2】:

除了@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);

【讨论】:

【参考方案3】:

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

您可以使用多个 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());
);

【讨论】:

是否有相关文档的链接? @m.spyratos 这里是文档链接firebase.google.com/docs/firestore/query-data/…【参考方案4】:

Firebase 版本 9

docs 没有涵盖这一点,但这里是如何将条件 where 子句添加到查询中

import  collection, query, where  from 'firebase/firestore'

const queryConstraints = []
if (group != null) queryConstraints.push(where('group', '==', group))
if (pro != null) queryConstraints.push(where('pro', '==', pro))
const q = query(collection(db, 'videos'), ...queryConstraints)

这个答案的来源是我最好的朋友 J-E^S^-U-S 的一些直觉猜测和帮助

【讨论】:

【参考方案5】:

例如,有一个数组是这样的

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

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

【讨论】:

【参考方案6】:

如果你使用的是角火,你可以像这样使用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 子句完成),请参阅 here。

【讨论】:

【参考方案7】:
async yourFunction()
    const Ref0 = firebase.firestore().collection("your_collection").doc(doc.id)

    const Ref1 = appointmentsRef.where('val1', '==',condition1).get();
    const Ref2 = appointmentsRef.where("val2", "!=", condition2).get()

    const [snapshot_val1, snapshot_val2] = await Promise.all([Ref1, Ref2]);

    
    const val1_Array = snapshot_val1.docs;
    const val2_Array = snapshot_val2.docs;

    const globale_val_Array = val1_Array .concat(val2_Array );

    return globale_val_Array ;
  



/*Call you function*/
this.checkCurrentAppointment().then(docSnapshot=> 
      docSnapshot.forEach(doc=> 
          console.log("Your data with multiple code query:", doc.data());
      );
    );

【讨论】:

【参考方案8】:

请注意,多个WHERE 子句本质上是AND 操作。

【讨论】:

以上是关于Firestore:多个条件 where 子句的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Firestore 7.24.0 实例中查询具有多个 where 子句的数据?

iOS - Firestore 复合索引中的索引上的多个 orderBy 和 where 子句

Linq to SQL 多个条件 where 子句

配置数据源Where子句怎么添加多个查询条件并且用OR相连

如何使用 where 子句从 Firestore 中删除文档

Telerik OpenAccess 和 where 子句中的多个条件