如何查询一个字段然后在Firebase云Firestore中按另一个字段排序?

时间:2017-11-02 01:02:00

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

我很难在firebase云端防火墙中进行(不那么)复杂的查询。

我只需要将所有文档where id字段==作为给定的ID。

然后按date订购结果,并限制为10个结果。

所以这是我目前的情况



db.firestore().collection('comments')
        .where("postId",'==',idOfThePost)
        .orderBy('date','asc').limit(10).get().then( snapshot => {
           //Nothing happens and the request wasn't even been executed
         })




只有在我不使用orderBy查询但我必须根据应用程序的需要处理此排序时,我才能得到结果。

有人有想法帮我解决这个问题吗?

感谢

6 个答案:

答案 0 :(得分:3)

您可以通过在Firestore中创建索引来实现此目的。

索引的第一个字段应该是相等字段,索引的第二个字段应该是按字段排序。

鉴于您的问题,您将需要以下索引:

first field: postId, 'asc'
second field: date, 'asc'

答案 1 :(得分:1)

请检查doc。它说

  

但是,如果您的过滤器具有范围比较(<,< =,>,> =),则您的第一个排序必须位于同一个字段

你可以试试这段代码

db.firestore().collection('comments')
    .where("postId",'==',idOfThePost)
    .orderBy('postId')
    .orderBy('date','asc').limit(10).get().then( snapshot => {
       .....
     })

答案 2 :(得分:1)

昨天我在Android上遇到了同样的问题。回调没有被调用。今天我突然收到一条错误信息。 FAILED_PRECONDITION: The query requires an index.它甚至在错误消息中包含一个URL,只需单击一下即可生成该索引。

似乎如果要对数据使用orderBy,则需要为该字段创建索引。索引也需要处于正确的顺序(DESC,ASC)。

答案 3 :(得分:1)

在这里,为什么不能这样做很奇怪。下面是另一个样本。无法得到结果。希望firebase可以回复此问题并更新文档。

dbFireStore.collection('room').where('user_id.'+global.obj_user.user_id,'==',true).orderBy('last_update').get().then((qs)=>{
  console.log(qs);
});

使用其他解决方案是javascript arrayarray.sort()

答案 4 :(得分:1)

我的解决方法

如果您要对此进行搜索,则可能已经意识到它是传统上无法完成的。根据您的问题,尽管可能会有一些可行的解决方法,但我刚刚创建了这个方法。

场景

我们有一个应用程序,该应用程序的帖子显示在供稿中(类似于Reddit),每个帖子的算法得分均为“得分”,我们需要一种方法来获取12-24小时前的“热门帖子”。由于Firebase不允许在另一个字段上使用降序排序的多个条件查询或单个条件查询,因此尝试查询时间戳使用>和<来构建12-24小时前的范围的“分数”排序失败。

解决方案

我们最终要做的是使用第二个字段,它是数组,因为您可以对数组包含和降序的查询进行复合。在发布信息时,我们知道当前时间,假设距服务器时代(即floor(serverTime/60.0/60.0))为10000小时。我们将创建一个名为arrayOfHoursWhenPostIsTwelveToTwentyFourHoursOld的数组,并在该数组中填充以下值:

int hourOffset = 12;
while (hourOffset <= 24) {
    [arrayOfHoursWhenPostIsTwelveToTwentyFourHoursOld addObject:@(currentHour+hourOffset)];
    hourOffset++;
}

然后,在发布帖子时,我们将该数组存储在字段hoursWhenPostIsTwelveToTwentyFourHoursOld

如果,例如,距帖子发布已经13个小时了(该帖子发布于10000小时),那么当前时间就是10013,因此我们可以使用array-contains查询来查看我们的数组是否包含值10013,同时也按算法得分排序

像这样:

FIRFirestore *firestore = [Server sharedFirestore];
FIRCollectionReference *collection = [firestore collectionWithPath:@"Posts"];
FIRQuery *query = [collection queryOrderedByField:@"postsAlgorithmScore" descending:YES];
query = [query queryWhereField:@"hoursWhenPostIsTwelveToTwentyFourHoursOld" arrayContains:@(currentHour)];
query = [query queryLimitedTo:numberToLoad];

几乎完成了

上面的代码由于使用复合索引查询而最初无法正常运行,因此我们必须在firebase中创建复合索引查询,最简单的方法是运行查询,然后查看错误日志和Firebase SDK将为您生成一个链接,您可以导航到该链接,它将为您自动生成数据库的复合索引,否则,您可以导航至firebase> database> index> compound> new并使用以下内容自行构建hoursWhenTwelveToTwentyFourHoursOld: Arrays, score: Descending

享受!

答案 5 :(得分:0)

根据firestore document

如果尝试使用不映射到现有索引的range子句进行复合查询,则会收到错误消息。该错误消息包括一个直接链接,用于在Firebase控制台中创建缺少的索引。

因此,只需单击您在Logcat中获得的链接,它将被重定向到创建索引页面,只需创建索引。需要一些时间。启用复合索引后,您将获得所需的查询结果。