喜欢查询和订购

时间:2019-02-24 08:55:59

标签: java firebase google-cloud-firestore

我在Google Cloud Firestore中的查询条件有问题。

任何人都可以帮助我。

This is my Collection and documents

下面是我的代码,以获得第一个以HA_开头并按ID DESC排序的文档

public Article getLastArticleProvider() {
    ApiFuture<QuerySnapshot> query = firebaseDB.getTblArticles()
            .whereGreaterThanOrEqualTo("articleId", "HA_")
            .orderBy("id", Query.Direction.DESCENDING)
            .limit(1)
            .get();

    QuerySnapshot snapshotApiFuture;
    Article article = null;

    try {
        snapshotApiFuture = query.get();
        List<QueryDocumentSnapshot> documents = snapshotApiFuture.getDocuments();
        for (QueryDocumentSnapshot document : documents) {
            article = document.toObject(Article.class);
        }
    } catch (InterruptedException | ExecutionException e) {
        return null;
    }
    return article;
}

我想获取文章ID为“ HA_”或“ XE_”开头的文章的最后ID

上图的EX:

  • if(articleId以“ HA_”开头)=>返回ID为831的对象
  • if(articleId以“ XE_”开头)=>返回ID为833的对象

现在我得到一个错误

  

java.util.concurrent.ExecutionException:com.google.api.gax.rpc.InvalidArgumentException:io.grpc.StatusRuntimeException:INVALID_ARGUMENT:不等式过滤器属性和第一排序顺序必须相同:articleId和id

3 个答案:

答案 0 :(得分:5)

TL;DR

在您的不等式过滤器属性之后添加一个虚拟顺序并更改您的查询优先级以满足您的需求。

我在 javascript 上遇到了同样的问题,但我相信它是 java 的解决方案。

完整解决方案:

当我运行查询时:

module.exports.getLastGroupChat = async function (groupId) {
    let colRef = db.collection('messages')
    colRef = colRef.where('groupId', '==', groupId)
    colRef = colRef.where('userId', '!=', '')
    colRef = colRef.orderBy('timestamp', 'desc').limit(1)
    const doc = await colRef.get()
    return doc

}

并收到:

<块引用>

不等式过滤器属性和第一排序顺序必须相同: 用户 ID 和时间戳

为了解决这个问题,首先我必须在不等式过滤器之后添加一个具有相同不等式属性的排序顺序。

此外,为了实现不等式属性的虚拟排序,我不得不更改查询优先级。

注意:您可以对同一个查询运行 where -> order -> where -> order

module.exports.getLastGroupChat = async function (groupId) {
    let colRef = db.collection('messages')
    colRef = colRef.where('userId', '!=', '')
    colRef = colRef.orderBy('userId', 'desc')
    colRef = colRef.where('groupId', '==', groupId)
    colRef = colRef.orderBy('timestamp', 'desc').limit(1)
    const doc = await colRef.get()
    return doc
}

该查询在我的本地调试 Firestore 上运行良好。将您的更改推送到您的 Firebase 云函数并触发您的函数。检查您的函数日志,您可能会收到索引错误。

<块引用>

查询需要索引。您可以在此处创建它:https://console.firebase.google.com/v1/r/project..

确保您进入链接并建立索引。大约需要五到十分钟才能生效。然后再次运行您的功能,一切都应该没问题。

玩得开心! :)

答案 1 :(得分:1)

如以下错误所述:

  

不平等过滤条件属性和第一排序顺序必须相同:articleId和id

因此,对于articleIdid,您不能使用不同的属性同时过滤元素并对其进行排序。

official documentation中,还有一个如何执行此操作的示例:

  • 范围过滤器和一阶按不同字段

    citiesRef.whereGreaterThan("population", 100000).orderBy("country"); //Invalid
    

因此,要解决此问题,您应该对同一文档属性进行过滤和排序。

答案 2 :(得分:0)

也许自从提出这个问题以来,firebase 已经改变了一些事情。

答案是您可以对不同的字段进行过滤和排序。

您可以链接 orderby 和过滤器,但是,如果您先进行过滤,则必须先通过该过滤器进行排序,然后才能通过任何其他字段进行排序。 例如

citiesRef.where('population', '>', 2500000).orderBy('population').orderBy('country');

在他们的文档中。 https://firebase.google.com/docs/firestore/query-data/order-limit-data#order_and_limit_data

However, if you have a filter with a range comparison (<, <=, >, >=), your first ordering must be on the same field, see the list of orderBy() limitations below.

你可以链接不同领域的 orderBys,我只是在我的一个查询中做到了。 (第一次运行可能会报错,它会要求你创建一个索引,它甚至有一个创建索引的链接)

await db.collection('daily_equipments').where('date', '<', tomorrow._d).where('date', '>=', date).orderBy('date').orderBy('order','asc').get();