如何在Cloud Firestore中使用逻辑OR执行复合查询?

时间:2017-10-08 14:12:55

标签: database firebase google-cloud-platform google-cloud-firestore

来自the docs

  

您还可以链接多个where()方法以创建更具体的查询(逻辑AND)。

如何执行OR查询? 示例:

  1. 向我提供字段statusopenupcoming
  2. 的所有文件
  3. 向我提供字段status == opencreatedAt <= <somedatetime>
  4. 的所有文件

10 个答案:

答案 0 :(得分:14)

OR不受支持,因为服务器难以扩展它(需要将状态保持为重复数据删除)。解决方法是发出2个查询,每个条件一个,以及客户端上的重复数据删除。

答案 1 :(得分:2)

我没有&#34;状态&#34;字段,但与状态相关的字段,根据请求将其更新为true或false,如

{ name: "a", status_open: true, status_upcoming: false, status_closed: false}

但是,请检查Firebase云功能。您可以更改功能侦听状态,更新与状态相关的属性,如

{ name: "a", status: "open", status_open: true, status_upcoming: false, status_closed: false}

一个或另一个,您的查询可能只是

...where('status_open','==',true)...

希望它有所帮助。

答案 2 :(得分:2)

借助recent addition of IN queries,Firestore支持“同一字段上具有逻辑 OR 的多达10个相等子句”

(1)的可能解决方案是:

documents.where('status', 'in', ['open', 'upcoming']);

请参见Firebase Guides: Query Operators | in and array-contains-any

答案 3 :(得分:0)

您可以使用rxjs merge运算符绑定两个Observable。 这里有一个例子。

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/merge';

...

getCombinatedStatus(): Observable<any> {
   return Observable.merge(this.db.collection('foo', ref => ref.where('status','==','open')).valueChanges(),
                           this.db.collection('foo', ref => ref.where('status','==','upcoming')).valueChanges());
}

然后您可以使用上述方法订阅新的Observable更新:

getCombinatedStatus.subscribe(results => console.log(results);

我希望这可以帮助你,来自智利的问候!!

答案 4 :(得分:0)

建议也为状态赋予价值。
前。

{ name: "a", statusValue = 10, status = 'open' }

{ name: "b", statusValue = 20, status = 'upcoming'}

{ name: "c", statusValue = 30, status = 'close'}

您可以ref.where('statusValue', '<=', 20)进行查询,然后找到'a''b'

这可以节省您的查询成本和性能。

顺便说一下,它并没有解决所有情况。

答案 5 :(得分:0)

我们现在有同样的问题,幸运的是,我们的唯一可能的值是A,B,C,D(4),因此我们必须查询类似A || B,A || C,A ||的值。 B || C,D等


大约几个月前,firebase支持一个新查询array-contains,因此我们要做的是制作一个数组,并对数组的OR值进行预处理

if (a) {
array addObject:@"a"
}
if (b) {
array addObject:@"b"
}
if (a||b) {
array addObject:@"a||b"
}
etc

我们对所有4!值或存在许多组合的情况进行此操作。

我们可以简单地检查查询[document arrayContains:@"a||c"]或我们需要的任何类型的条件。

因此,如果某些内容仅符合我们4个条件(A,B,C,D)中的条件A,则其数组将包含以下文字字符串:@["A", "A||B", "A||C", "A||D", "A||B||C", "A||B||D", "A||C||D", "A||B||C||D"]

然后对于任何OR组合,我们都可以根据需要搜索array-contains(例如“ A || C”)


注意:仅当您有几个可能的值要进行“或”比较时,这才是合理的方法。

有关Array-contains here的更多信息,因为它是Firebase文档的新功能

答案 6 :(得分:0)

不支持

但是,如果需要,您可以在代码中完成

例如:如果我要查询的商品(尺寸等于Xl或XXL:并且性别是男性)

productsCollectionRef
                //1* first get query where can firestore handle it
                .whereEqualTo("gender", "Male")
                .addSnapshotListener((queryDocumentSnapshots, e) -> {

                    if (queryDocumentSnapshots == null)
                        return;

                    List<Product> productList = new ArrayList<>();
                    for (DocumentSnapshot snapshot : queryDocumentSnapshots.getDocuments()) {
                        Product product = snapshot.toObject(Product.class);

                        //2* then check your query OR Condition because firestore just support AND Condition
                            if (product.getSize().equals("XL") || product.getSize().equals("XXL"))
                                productList.add(product);
                    }

                    liveData.setValue(productList);

                });

答案 7 :(得分:0)

对于Flutter dart语言,请使用以下代码:

request.prototype.on('error', (e) => doSomething())`

答案 8 :(得分:0)

这不能解决所有情况,但是对于“枚举”字段,您可以通过为每个枚举值创建一个单独的布尔字段,然后为每个值添加where("enum_<value>", "==", false)来模拟“ OR”查询不是您想要的“ OR”子句的一部分。

例如,考虑您的第一个所需查询:

  1. 给我所有字段状态为打开或即将到来的文档

您可以通过将status: string字段拆分为多个布尔字段(每个枚举值一个)来实现此目的:

status_open: bool
status_upcoming: bool
status_suspended: bool
status_closed: bool

要执行“状态为打开或即将发生的状态”查询,请执行以下操作:

where("status_suspended", "==", false).where("status_closed", "==", false)

这是如何工作的?好吧,因为它是一个枚举,所以您知道必须为其中一个值分配true。因此,如果您可以确定所有 other 值都不与给定条目匹配,那么通过推导,它必须与您最初寻找的值之一匹配。

答案 9 :(得分:0)

实际上我发现@Dan McGrath的答案在这里工作是对他的答案的重写:

 private void query() {
        FirebaseFirestore db = FirebaseFirestore.getInstance();
        db.collection("STATUS")
                .whereIn("status", Arrays.asList("open", "upcoming")) // you can add up to 10 different values like : Arrays.asList("open", "upcoming", "Pending", "In Progress", ...)
                .addSnapshotListener(new EventListener<QuerySnapshot>() {
                    @Override
                    public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots, @Nullable FirebaseFirestoreException e) {

                        for (DocumentSnapshot documentSnapshot : queryDocumentSnapshots) {
// I assume you have a  model class called MyStatus

                            MyStatus status= documentSnapshot.toObject(MyStatus.class);
                            if (status!= null) {
                               //do somthing...!
                            }
                        }
                    }
                });

    }