为了账号安全,请及时绑定邮箱和手机立即绑定

字段上的 Firestore 查询顺序与不同字段上的过滤器

字段上的 Firestore 查询顺序与不同字段上的过滤器

至尊宝的传说 2022-07-06 15:56:09
我在 google Cloud Firestore 中遇到查询条件问题。任何人都可以帮助我。下面是我获取第一个以 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;}我想获取articleId以“HA_”或“XE_”开头的文章的最后一个ID例如上图:if(articleId start with "HA_") => return object of id 831if(articleId start with "XE_") => return object of id 833现在我得到一个错误java.util.concurrent.ExecutionException: com.google.api.gax.rpc.InvalidArgumentException: io.grpc.StatusRuntimeException: INVALID_ARGUMENT: 不等式过滤器属性和第一排序顺序必须相同:articleId 和 id
查看完整描述

3 回答

?
POPMUISE

TA贡献1765条经验 获得超5个赞

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


我在 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

}


并收到:


不等式过滤器属性和第一排序顺序必须相同:userId和timestamp


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


此外,我必须更改查询优先级以实现不等式属性的虚拟排序顺序。


注意:您可以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 ..。


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


玩得开心!:)


查看完整回答
反对 回复 2022-07-06
?
弑天下

TA贡献1818条经验 获得超7个赞

正如以下错误所说:

不等式过滤器属性和第一排序顺序必须相同:articleId 和 id

因此,在您的情况articleIdid.

官方文档中还有一个如何不做的例子:

  • 不同字段上的范围过滤器和一阶排序

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

所以要解决这个问题,你应该在同一个文档属性上进行过滤和排序。


查看完整回答
反对 回复 2022-07-06
?
浮云间

TA贡献1829条经验 获得超4个赞

自从提出这个问题以来,也许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();



查看完整回答
反对 回复 2022-07-06
  • 3 回答
  • 0 关注
  • 81 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信