javascript - Firestore 一个范围查询,在不同的字段上排序

标签 javascript firebase dart google-cloud-firestore

我有以下收藏/文件

Location Collection
{
  "geoHash" : "wwscjrm3nu01",
  "timeStamp" : "March 25, 2020 at 1:07:38 PM UTC-4" 
}
{
  "geoHash" : "wwscjrm2wc2h",
  "timeStamp" : "March 25, 2020 at 2:07:38 PM UTC-4" 
}

请用上面的例子替换 GeoHashs#

screenshot

因此,我试图通过按时间戳“DESC”对它们进行排序来查询这些 GeoHash 的范围,如下所示

    db.collection('location')
        .where('geoHash', '>=', 'wwkxt4kxmmvk')
        .where('geoHash', '<=', 'wwt4vsn22peq')
        .orderBy('timeStamp', 'DESC')
        .limit(15).get()

没有成功,请报错

Error getting documents { Error: 3 INVALID_ARGUMENT: inequality filter property and first sort order must be the same: geoHash and timeStamp
at callErrorFromStatus (/srv/node_modules/@grpc/grpc-js/build/src/call.js:30:26)
at Http2CallStream.call.on (/srv/node_modules/@grpc/grpc-js/build/src/call.js:79:34)
at emitOne (events.js:121:20)
at Http2CallStream.emit (events.js:211:7)
at process.nextTick (/srv/node_modules/@grpc/grpc-js/build/src/call-stream.js:97:22)
at _combinedTickCallback (internal/process/next_tick.js:132:7)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)
code: 3,
details: 'inequality filter property and first sort order must be the 
same: geoHash and timeStamp',
metadata: Metadata { internalRepr: Map {}, options: {} } }

如果我每个月或每天在此集合中有数千或数百万个文档怎么办!?你们中有人遇到过这个问题吗?最好的解决方法是什么?

更新 0.2

非常感谢您为解决此问题提供的帮助和支持。我已经重现了我最后看到的内容。

目前,我在 Node js 中使用以下查询

       db.collection('locations')
        .where('geoHash', '>=', 'wwkxt4kxmmvk')
        .where('geoHash', '<=', 'wwt4vsn22peq')
        .orderBy('geoHash')
        .orderBy('timeStamp', 'desc')
        .limit(15).get().then(snapshot => {
          if (snapshot.empty) {
            console.log('No matching documents.');
          }
          snapshot.forEach(doc => {
            console.log(doc.data());
          });
        });

预期是过滤 GeoHashs > 对 GeoHashs 排序 > 按时间戳排序。所以,最终结果假设是有序的时间戳,但我看到的是以下内容,

10:08:24.901 AM
   test
    { geoHash: 'wwscjrm3nu01',
      timeStamp: Timestamp { _seconds: 1585227600, _nanoseconds: 0 },
      post: '3' }
10:08:24.900 AM
   test
    { geoHash: 'wwscjrm3nu01',
      timeStamp: Timestamp { _seconds: 1585317000, _nanoseconds: 0 },
      post: '1' }
10:08:24.900 AM
   test
    { geoHash: 'wwscjrm2wc2h',
      timeStamp: Timestamp { _seconds: 1585314000, _nanoseconds: 0 },
      post: '2' }

正如您在上面的输出中看到的,我除了看到基于时间戳的 Post 1 > 2 > 3,但我在上面看到的是 Post 2 > 1 > 3。

最佳答案

所以你的工作查询是:

db.collection('locations')
  .orderBy("geoHash")
  .where('geoHash', '>=', range.lower)
  .where('geoHash', '<=', range.upper)
  .orderBy('timeStamp', 'DESC')
  .limit(15).get()

据我所知,您得到的结果是按 geoHash 排序的,然后才按 timeStamp 排序。所以:如果两个文档具有相同的 geoHash 值,它们将按照它们的 timeStamp 值排序。

这是按预期工作的:当您对一个字段进行范围查询时,您总是首先需要对该字段进行排序。由于您首先对该字段进行排序,因此结果会按该字段的顺序返回。

这是 Firestore 查询模型的固有特性,因此了解更多信息可能会有所帮助。它的性能保证意味着一旦找到查询的起点,它就必须始终能够从数据库中流式传输结果。重新排序未知数量的结果将无法始终满足该性能保证,因此不受支持的操作。

要按照时间戳顺序获取结果,您需要在应用程序代码中重新排序。

关于javascript - Firestore 一个范围查询,在不同的字段上排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60872122/

相关文章:

javascript - Protractor中使用describe或it时,使用function()和()有什么区别

javascript - (Javascript) 给定区间内的质数 : for loop doesn't iterate

reactjs - 如何在 Redux Action 中分离 firestore 监听器

swift - 更改 Firebase 观察器 SWIFT 4 后函数返回

dart - 带有图像背景 flutter 的按钮

flutter - Flutter已折叠ExpansionTile是否不保存表单数据?

javascript - 如何在 Javascript 中验证 Enter 键?

javascript - 在表单中提交时,新的 data-* HTML5/Javascript 值是否可以在 PHP 中访问

javascript - Firebase ES6 promise 提供文档

flutter - 在 Flutter 中显示来自互联网的图像