firebase 可以在接收数据时自动重新排序数据吗?

Posted

技术标签:

【中文标题】firebase 可以在接收数据时自动重新排序数据吗?【英文标题】:Can firebase automatically reorder data as it receives data? 【发布时间】:2015-01-03 21:42:02 【问题描述】:

这是场景:

1) 我有一个包含两个数据点的移动应用程序:位置和主题标题。

2) 我将这两点发送到 firebase。

3) 许多点是从不同位置和不同主题的各种设备发送的。

4) 移动设备随后请求特定位置的主题标题列表。

我的问题是: 在将集合返回给调用者之前,firebase 是否可以在数据库中按字母顺序自动重新排序这些主题标题?

基本上,我不希望移动设备重新排序任何东西,而只是直接显示数据集中的数据。

我想这必须在服务器端使用 javascript 代码完成,我只是不清楚它是如何在 firebase 中完成的。

提前致谢

【问题讨论】:

【参考方案1】:

看起来您有一个非常好的用例,但我不会尝试将其转换为适合您的工作应用程序。相反,我将提供一些指向最重要部分的指针,它们与 Firebase 相关。

数据结构

假设您使用此结构来表示您的兴趣点:

locations
    -123981234cbdag
        title: "White House"
        latitude: 38.897676
        longitude: -77.036528
    -458614tajsla12
        title: "Google San Francisco"
        latitude: 37.789635
        longitude: -122.390375

此 sn-p 中位置的名称/键(“-123981234cbdag”和“-458614tajsla12”)是 Firebase 在您调用其 push 方法时生成的格式。

按特定顺序从 Firebase 检索数据

Firebase 可以按任意顺序向您的应用程序提供位置:

    按他们的键(当您使用 push 时也是按时间顺序排列的) 按他们的优先级(上面的例子中没有显示) 任何子属性的值

每个代码:

// we call this helper function below to print the locations
function printSnapshot(locations) 
    locations.forEach(function(snapshot) 
        console.log(snapshot.val().title);
    );

var ref = new Firebase('https://your.firebaseio.com/locations');

// 1a. gives a snapshot with the children in order of their key
ref.on('value', printSnapshot);

// 1b. the same result, but explicitly orders the keys in order of their name
ref.orderByKey().on('value', printSnapshot);

// 2. gives a snapshot with the children in the order of their priority
ref.orderByPriority().on('value', printSnapshot);

// 3a. gives a snapshot with the children in the order of their title
ref.orderByChild('title').on('value', printSnapshot);

// 3b. gives a snapshot with the children in the order of their latitude
ref.orderByChild('latitude').on('value', printSnapshot);

// 3c. gives a snapshot with the children in the order of their longitude
ref.orderByChild('longitude').on('value', printSnapshot);

订购数据后,您还可以限制检索的内容。

检索较少的可用位置

这个 sn-p 只会返回白宫:

ref.orderByChild('title').equalTo('White House').on('value', printSnapshot);

sn-p 也会这样:

ref.orderByChild('title').limitToLast(1).on('value', printSnapshot);

但是,一旦您的一位用户访问Zion National Park,最后一个可能会返回不同的位置。另外值得注意的是,最后一个 sn-p 将自动接收可能出现在您的 Firebase 中的任何新值,因为 Firebase 会主动同步适合您查询的数据。

所以流程可能是:

    您的应用程序已启动 它运行上面的查询,当按标题排序时询问最后一个位置 Firebase 将白宫位置发送到您的应用程序,您的应用程序会显示该位置 有人访问了锡安国家公园并将该数据插入 Firebase Firebase 将锡安国家公园的位置发送到您的应用程序 等

按纬度或经度过滤

好的,我们在这里有点分心。让我们回到您的用例。我假设您知道用户的位置,但如果您不知道,请查看this question。

var whereAmI =  latitude: 38.898042, longitude: -77.03326;

如果有人准确地添加了该用户所在的位置,我们可以像以前一样使用equalTo。但鉴于 GPS 设备的精度不同,这将不是很可靠。因此,我们应该检查附近的位置,以便在我们的纬度/经度的特定范围内。

我们可以使用 Firebase 的 startAtendAt 方法:

ref
  .orderByChild('latitude')
  .startAt(whereAmI.latitude - 0.002)
  .endAt(whereAmI.latitude + 0.002)
  .on('value', printSnapshot);

这个 sn-p 将返回您所在位置以东或以西几百米内的位置,这...猜猜看...只是我们样本数据集中的白宫!

如果我们添加limitToFirst(1),它甚至会限制返回的位置数量。但不幸的是,它会返回最东端的位置,这不一定是离我最近的位置。 (我对纬度不太好,可能也是最西的位置)另外,它只适合纬度;您还想使用经度来查找您正北或以南的位置。

理想情况下,您可以在 Firebase 中执行类似的操作:

// !!!THIS IS A NON-WORKING EXAMPLE!!!
ref
  .orderByChild('latitude')
  .startAt(whereAmI.latitude - 0.002)
  .endAt(whereAmI.latitude + 0.002)
  .orderByChild('longitude')
  .startAt(whereAmI.longitude- 0.002)
  .endAt(whereAmI.longitude+ 0.002)
  .on('value', printSnapshot);
// !!!THIS IS A NON-WORKING EXAMPLE!!!

但不幸的是,Firebase 目前每个查询只能过滤一个孩子。所以要么我们必须检索地球整个纬度片中的所有孩子并过滤客户端或者我们必须找到一种方法将纬度和经度填充到一个单一的该属性还保持了良好的“可以轻松排序”的数字属性。

输入“Geohashes”和 GeoFire。

按 Geohash 过滤(使用 Geofire)

如果您访问Firebase's demo of real-time public transport information,您会看到一些非常接近您的用例的东西。它显示了某个区域内的所有 MUNI(旧金山公共交通)线路。

来自移动设备的屏幕截图,因为我在桌面界面中找不到一张(无论如何看起来都非常相似)

如果您等待几秒钟(并且在营业时间内访问),您甚至会看到车辆四处移动。他们显示的区域是一个圆圈,所以很明显,编写该演示的人想出了如何同时查询纬度和经度。

他们使用的技巧称为Geohashing,引用Wikipedia:

这是一种分层的空间数据结构,将空间细分为网格形状的桶。

Geohashes 提供任意精度等属性,以及逐渐从代码末尾删除字符以减小其大小(并逐渐失去精度)的可能性。

由于精度逐渐下降,附近的地方经常(但不总是)出现相似的前缀。共享前缀越长,两地距离越近。

这听起来像是像您这样的应用程序的秘诀:geohash 将纬度和经度编码为一个可以订购的值。我建议玩一下 geohashes。由于最初的 geohash.org 似乎已关闭,我使用了the Geohash service of openlocation.org。它甚至从白宫周围开始,显示我们上面的位置在这些 Geohashes 周围的某个地方:('dqcm0n','dqcm0h','dqcm0m','dqcjpv','dqcjpy','dqcm0q','dqcm0k','dqcjpu','dqcm0j')

Firebase 的人也意识到这将非常有用,因此他们创建了一个名为 Geofire 的帮助程序库。有一个很棒的introduction and tutorial for GeoFire on Firebase's web site。我建议你从那里继续工作。

【讨论】:

哇,这绝对清除了很多东西!谢谢!

以上是关于firebase 可以在接收数据时自动重新排序数据吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Firebase/Firestore 具有重新排序功能的任务列表

如何在快速更改(Firebase)时接收/更新数据

在asp.net mvc中删除数据成功后重新排序自动编号列JQuery Datatable

如何访问另一个firebase项目的数据

当应用程序通过使用 firebase_messaging 的推送通知终止时如何接收自定义数据?

在 Flutter 应用程序上过滤和排序 Firebase (Firestore) 数据