Firebase Firestore - OR 查询

44
如何通过一个字段的多个值获取数据?例如,我有一个帖子数据库,想要查询所有博客ID为1或2的帖子,并按时间戳排序。
collection("posts").whereEqualTo("blogId", "1")
.whereEqualTo("blogId", 2).orderBy("timestamp", Query.Direction.DESCENDING).limit(50)

上面的代码不起作用 :(

如何实现呢? 谢谢 :)


这现在是可能的,因为有11月7日的更新。请更新接受的答案:https://dev59.com/w1YN5IYBdhLWcg3w5ruY#59039919 - Albert Renshaw
除了下面的答案之外,我认为这个资源会有所帮助。 - Alex Mamo
12个回答

43

Firestore现在支持“IN”查询,以实现此目的。

查询将如下所示:

database.collection("collectionName").where("fieldName", "in", ["fieldValue1", "fieldValue2"]);

您最多可以有10个值(fieldValueX)来检查是否为“IN”。


OP想要的代码如下:

database.collection("posts").where("blogId", "in", ["1", "2"]); 

7
多个领域怎么办? - Israel Obanijesu
2
据我所知,您将不得不使用复合查询来实现此目的,但最好检查Firebase文档以确保。我不太熟悉这样的查询。 - Albert Renshaw
7
好的,虽然这是 Firebase 方面非常糟糕的实现方式,但回答不错。而且还有一个非常紧的限制,只能有 10 个值... - Kisinga

20

你可以将这些 Observables 结合起来并返回为一个

orQuery(){

    const $one = this.afs.collection("posts", ref => ref.where("blogId","==","1")).valueChanges();
    const $two = this.afs.collection("posts", ref => ref.where("blogId","==","2")).valueChanges();

    return combineLatest($one,$two).pipe(
        map(([one, two]) => [...one, ...two])
    )
}

getOr(){
    this.orQuery().subscribe(data => console.log(data))
}

3
请注意,在这种方法中,最终结果可能会包含重复项,这取决于查询(在这种情况下,由于使用相同字段进行查询但值不同,不会有重复项)。 - Lahiru Chandima
如果我们使用多个字段来分页数据,可能会很困难。 - Le Khiem
非常好的清晰答案 - 非常感谢 - 可惜这是最佳方法,Google 无法提供更好的解决方案。 - danday74

8
Firebase已经听取了我们的请求,并在2019年11月7日推出了IN查询。这是一种OR查询,您可以使用多达10个OR过滤器。
对于Android:
collection("posts").whereIn("blogId", Arrays.asList("1", "2"))
.orderBy("timestamp", Query.Direction.DESCENDING).limit(50);

Firebase文档


应该是正确答案。 - Rodrigo Borba

6

OR操作符在Firebase Firestore中不被接受:

Cloud Firestore对逻辑或查询的支持有限。in和array-contains-any 操作符支持单个字段上最多10个相等(==)或包含数组(array-contains)条件的逻辑或运算。对于其他情况,请为每个OR条件创建单独的查询,并在应用程序中合并查询结果。

Cloud Firestore中的查询,查询限制

通常使用Firebase语法可以调用两个集合:

const res1 = async collection("posts", ref => ref.where('blogId', '==', 1).get();
const res2 = async collection("posts", ref => ref.where('blogId', '==', 2).get();

您可以在呈现视图之前合并结果。

但如果您有blogIds,可以使用以下语法:collection("posts").orderBy('blogId').startAt(1).endAt(2);

例如:


5

我找不到关于将where条件进行OR操作的文档。但是您可以通过以下方式重新表达对blogId的要求:

WHERE blogId > 0 AND blogId < 3

试试这段代码:

collection("posts")
.where("blogId", ">", "0")
.where("blogId", "<", "3")
.orderBy("timestamp", Query.Direction.DESCENDING)
.limit(50)

4
是的,但我的情况有点复杂。我有一个应用程序,用户可以订阅一些博客。因此,我需要检索几个ID的所有最新文章(可以是2、5或更多个ID)。这些ID是自动生成的(例如WordPress - 831cacax613das)或来自Blogger(对于Blogspot博客-12320183127312307212)。 我目前正在使用带有Elasticsearch的Firebase数据库,但我有兴趣迁移到Firestore。 - Skye
1
点击此处查看如何使用集合:https://cloud.google.com/firestore/docs/solutions/arrays - Tim Biegeleisen
嗯,我可以使用单元素映射将blogId存储起来,并像示例中那样查询它,但在这种情况下,每个blogId都需要为其创建一个独立的索引。目前我的数据库中有300个博客,但如果有几千个呢?:D 即使我将其存储在具有整数值而不是布尔值的映射中,我也只能查询一个字段,因此无法调用此操作:.whereGreaterThan("blogIdMap.kqy04zya72zit5x7n9", 0) .whereGreaterThan("blogIdMap.kqy0n2dt2maqluvi3eu", 10) - Skye
@TimBiegeleisen 这个可行吗?因为我所读到的是,当使用范围比较时,你只能在应用比较的键上使用orderBy。在这种情况下,只有“blogId”可以使用orderBy。所以在“timestamp”上使用orderBy是不起作用的。你能否确认一下它是否有效? - Sandip Fichadiya
@TimBiegeleisen 我不是那个意思 :) 我的意思是,如果你记得在使用Firestore时它对你有用。 - Sandip Fichadiya
显示剩余6条评论

4

Firestore现在支持OR查询(预览版),如果您想在多个字段上执行OR操作,这可能会很有用。 您可以从Firebase SDK v24.4.5中使用它。

// Returns all documents with capital = true OR population > 1000000
Query query = collection.where(Filter.or(
        Filter.equalTo("capital", true),
        Filter.greaterThanOrEqualTo("population", 1000000)
));

3

对于Android用户,请注意Firestore现在支持逻辑OR查询。因此,您现在可以在多个字段上执行OR查询。该选项从Cloud Firestore版本24.4.5开始提供。

在代码中,它将非常简单:

val db = Firebase.firestore
val citiesRef = db.collection("cities")
val query = citiesRef.where(Filter.or(
        Filter.equalTo("capital", true),
        Filter.greaterThanOrEqualTo("population", 1000000)    
))

将返回 capital 设置为 true 的文档,或者人口大于或等于 1_000_000 的文档。


2

1

Firestore没有OR查询。您可以通过运行两个查询并将它们拼接起来来完成这项工作。

例如,您可以:

const search = ( key, value ) =>  collection( 'users' ).where( key, '==', value ).get().then( doc => doc.data() )

Promise.all( [ search( 'name', 'John' ), search( 'name', 'Johnny' ) ] )
.then( ( [ one, two ] ) => one.concat( two ) )
.then( allResults => dothings() )

1

对于Android,我正在使用这样的OR查询。

List<String> values = new ArrayList<>();
    values.add("Value 1");
    values.add("Value 2");

然后像这样使用 .whereIn 查询。
db.collection("collectionName")
            .whereIn("fieldName", values)   // where values is the list we created
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {

                    if (task.isSuccessful()) {

                      // Do your stuff

                    }

                }
            });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接