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

Can firebase automatically reorder data as it receives data?

场景如下:

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

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

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

4) 移动设备然后请求某个位置的主题标题列表。

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

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

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

提前致谢

看起来你有一个非常好的 use-case,但我不会尝试将它翻译成适合你的工作应用程序。相反,我将提供一些指向最重要部分的指针,它们与 Firebase 相关。

数据结构

假设您将此结构用于您的兴趣点:

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

此代码段中位置的 names/keys(“-123981234cbdag”和“-458614tajsla12”)是 Firebase 在您调用其 push 方法时生成的格式.

按特定顺序从 Firebase 检索数据

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

  1. 他们的钥匙(当你使用 push 时也是按时间顺序排列的)
  2. 他们的优先级(在上面的例子中没有显示)
  3. 任意值child属性

每个代码:

// 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);

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

检索较少的可用位置

这段代码只会 return 白宫:

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

这段代码也会如此:

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

但是,一旦您的某个用户访问 Zion National Park,最后一个位置可能 return 不同。还要注意的是,最后一个代码段将自动接收可能出现在您的 Firebase 中的任何新值,因为 Firebase 会主动同步适合您查询的数据。

所以流程可能是:

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

按纬度或经度过滤

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

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

如果有人准确地添加了该用户所在的位置,我们可以像以前一样使用 equalTo。但考虑到 GPS 设备的精度各不相同,这将不是很可靠。因此,我们应该检查附近的位置,以便在我们的 latitude/longitude.

的特定范围内

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

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

此代码段将 return 您所在位置以东或以西几百米范围内的位置,这...猜猜...就是我们示例数据集中的白宫!

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

理想情况下,您可以在 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 目前每个查询只能过滤一个 child。所以 要么 我们必须检索地球的整个纬度切片中的所有 children 并过滤 client-side 我们必须找到一种方法将纬度和经度填充到单个 属性 中,同时保持数字的“可以轻松订购”的良好特性。

输入“Geohashes”和 GeoFire。

通过 Geohash 过滤(使用 Geofire)

如果你去 Firebase's demo of real-time public transport information,你会看到一些与你的 use-case 非常接近的东西。它显示特定区域的所有 MUNI(旧金山 public 交通)线路。

手机截图,因为我找不到桌面界面的(反正看起来很像)

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

他们使用的 trick 称为 Geohashing 并引用 Wikipedia:

It is a hierarchical spatial data structure which subdivides space into buckets of grid shape.

Geohashes offer properties like arbitrary precision and the possibility of gradually removing characters from the end of the code to reduce its size (and gradually lose precision).

As a consequence of the gradual precision degradation, nearby places will often (but not always) present similar prefixes. The longer a shared prefix is, the closer the two places are.

这听起来像是像您这样的应用程序的秘诀:geohash 将纬度和经度编码为单个值,可以对其进行排序。我建议玩一下 geohashes。由于原来的geohash.org好像down了,所以我用了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。我建议你从那里继续工作。