javascript - Firebase 版本 9 使用多个条件 where 子句
问题描述
我正在将一个项目从 Firebase 版本 8 更新到版本 9。我有条件过滤查询,过去的结构如下:
let query = db.collection("collectionName").orderBy("timestamp")
if (filters.selectedStaff) {
query = query.where("id", "==", filters.selectedStaff.id);
}
if (filters.selectedStudent) {
query = query.where("studentIDs", "array-contains", filters.selectedStudent.id);
}
然后查询在每次过滤器更改时重新呈现的钩子中执行。使用版本 8,这可以完美运行。
在版本 9 中,现在构建查询以遵循每个查询作为参数传递给查询函数的格式。一个普通的查询看起来像:
query(collection(db, "collectionName"), where("id", "==", filters.selectedStaff.id), where("studentIDs", "array-contains", filters.selectedStudent.id), orderBy("timestamp"))
您仍然可以将 where 函数存储为变量,并将该变量作为参数传递给查询函数:
let w1 = where("id", "==", filters.selectedStaff.id)
let w2 = where("studentIDs", "array-contains", filters.selectedStudent.id)
query(collection(db, "collectionName"), w1, w2, orderBy(timestamp))
但是,我还没有想出如何解决的问题是如何使 where 子句有条件。firebase 似乎不允许 where 子句值是任何值。例如,使 w1 默认为:
let w1 = where("id", "==", "*")
如果您尝试使运算符也成为变量并默认为 == 以外的任何内容,例如 != :
let w1 = where("id", "!=", "")
Firebase 强制您按 where 子句中的字段设置主要排序,如果您尝试按像我这样的另一个字段(时间戳)进行排序,这将不起作用。
最终,可行的解决方法是在每个文档中创建一个具有相同值的字段,例如布尔真值,然后将所有 where 子句设置为最初等于该值,然后动态更改:
let w1 = where("randomField", "==", true)
let w2 = where("randomField", "==", true)
if(filters.selectedStaff){
w1 = where("id", "==", filters.selectedStaff.id)
}
if(filters.selectedStudent){
w2 = where("studentIDs", "array-contains", filters.selectedStudent.id)
}
query(collection(db, "collectionName"), w1, w2, orderBy(timestamp))
虽然这可行,但感觉确实是一种不必要的解决方法,我想看看是否有人知道实现相同结果的更好方法。
解决方案
您可以继续使用现有的逻辑,只是语法发生了变化。尝试重构代码,如下所示:
let q = query(collection("db", "collectionName"), orderBy("timestamp"));
if (filters.selectedStaff) {
q = query(q, where("id", "==", filters.selectedStaff.id));
}
if (filters.selectedStudent) {
q = query(q, where("studentIDs", "array-contains", filters.selectedStudent.id));
}
const snapshot = await getDocs(q);
另一种方法是有条件地将这些条件推送到数组中:
const conditions = [orderBy("timestamp")]
if (filters.selectedStaff) {
conditions.push(where("id", "==", filters.selectedStaff.id));
}
if (filters.selectedStudent) {
conditions.push(where("studentIDs", "array-contains", filters.selectedStudent.id));
}
const q = query(collection(db, "collectionName"), ...conditions);
// Do note the spread operator ^
const snapshot = await getDocs(q);
推荐阅读
- python - 使用多处理时,输入函数在 python 中过早结束
- algorithm - 给定一些四舍五入的数字,如何找到原始分数?
- html - 具有粘性位置的标题自动隐藏
- python - 如何在 selenium python 中修改 innerHTML
- sql - BigQuery 在带有通配符表的视图中查询 _TABLE_SUFFIX
- android - 在android中创建自定义条形图
- lua - zerobrane 中未捕获的 lua 异常错误,有什么解决方案吗?
- php - 调用未定义的方法 CodeIgniter\Database\MySQLi\Builder::num_rows()
- apache-spark - 如何在 Python 中将 Kafka 主题数据加载到 Spark Dstream 中
- python - 中断和重新启动 python 脚本