火还原: 多个条件 where 子句

例如,我有动态过滤我的书籍清单,我可以设置特定的颜色,作者和类别。 此过滤器可以同时设置多种颜色和多个类别。

   Book > Red, Blue > Adventure, Detective.

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

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


.orderBy("date")
.get()
.then(querySnapshot => {...
62780 次浏览

正如您在 API 文档中看到的,收集()方法返回一个 收藏参考。CollectionReference 扩展了 质疑,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(...)
}

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

例如,有一个如下所示的数组

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
}

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

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());
});
});

如果你使用角度射击,你可以像这样使用 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 子句) ,请参见 给你

有关 Firebase Version 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());
});

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

火力基地第九版

医生没有涵盖这一点,但是这里介绍了如何向查询添加条件 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 的直觉猜测和帮助

由于 CollectionRef在 Firebase web 版本9中没有 query方法,

我修改了 @ abk的答案。

async getQueryResult(path, options = {}) {
/* Example
options = {
where: [
["isPublic", "==", true],
["isDeleted", "==", false]
],
orderBy: [
["likes"],
["title", "desc"]
],
limit: 30
}
*/


try {
let { where, orderBy, limit } = options;


let collectionRef = collection(<firestore>, path);
let queryConstraints = [];


if (where) {
where = where.map((w) => firestore.where(...w));
queryConstraints = [...queryConstraints, ...where];
}


if (orderBy) {
orderBy = orderBy.map((o) => firestore.orderBy(...o));
queryConstraints = [...queryConstraints, ...orderBy];
}


if (limit) {
limit = firestore.limit(limit);
queryConstraints = [...queryConstraints, limit];
}


const query = firestore.query(collectionRef, ...queryConstraints);
const querySnapshot = await firestore.getDocs(query);
const docList = querySnapshot.docs.map((doc) => {
const data = doc.data();
return {
id: doc.id,
...data,
};
});
return docList;
} catch (error) {
console.log(error);
}
}

一个简单的函数,您可以指定路径和过滤器数组,您可以传递和获取文档,希望它有所帮助。

async function filterDoc(path, filters) {
if (!path) return [];


//define the collection path
let q = db.collection(path);


//check if there are any filters and add them to the query
if (filters.length > 0) {
filters.forEach((filter) => {
q = q.where(filter.field, filter.operator, filter.value);
});
}


//get the documents
const snapshot = await q.get();


//loop through the documents
const data = snapshot.docs.map((doc) => doc.data());


//return the data
return data;
}


//call the function
const data = await filterDoc(
"categories_collection",
[
{
field: "status",
operator: "==",
value: "active",
},
{
field: "parent_id",
operator: "==",
value: "kSKpUc3xnKjtpyx8cMJC",
},
]
);