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

时间:2015-01-03 21:42:03

标签: firebase

以下是该方案:

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

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

3)许多积分都来自不同位置和不同科目的不同设备。

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

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

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

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

提前致谢

1 个答案:

答案 0 :(得分:7)

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

数据结构

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

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

此代码段中的位置的名称/键(" -123981234cbdag"以及" -458614tajsla12")具有Firebase在调用其{{{{{ 1}}方法。

按特定顺序从Firebase检索数据

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

  1. 用他们的密钥(当你使用push时也按时间顺序排列)
  2. 按其优先级(未在上述示例中显示)
  3. 以任何子属性的值
  4. 每个代码:

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

    这个片段也是如此:

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

    但是,如果您的某个用户访问Zion National Park,则最后一个可能会返回其他位置。另外值得注意的是,最后一段代码会自动收到Firebase中可能显示的任何新值,因为Firebase会主动同步符合您查询的数据。

    所以流程可能是:

    1. 您的申请已开始
    2. 运行上述查询,询问按标题排序时的最后位置
    3. Firebase将白宫位置发送到您的应用程序,应用程序显示
    4. 有人访问锡安国家公园并将该数据插入Firebase
    5. Firebase将锡安国家公园的位置发送到您的应用程序
    6. 按纬度或经度过滤

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

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

      如果有人准确添加了此用户所在的位置,我们可以像之前一样使用var whereAmI = { latitude: 38.898042, longitude: -77.03326}; 。但考虑到GPS设备的精度不同,这将不太可靠。因此,我们应该检查附近的位置,以便在我们的纬度/经度的某个范围内。

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

      endAt

      此片段将返回距您所在地东部或西部几百米范围内的位置,其中......猜测......在我们的示例数据集中只是白宫!

      如果我们使用ref .orderByChild('latitude') .startAt(whereAmI.latitude - 0.002) .endAt(whereAmI.latitude + 0.002) .on('value', printSnapshot); ,它甚至会限制返回的位置数量。但不幸的是,它将返回最东部的位置,这不一定是最接近我的位置。 (我对纬度不是很好,也可能是最西边的地方)此外,它只适合纬度;你也想用经度找到你北方或南方的位置。

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

      limitToFirst(1)

      但遗憾的是,Firebase目前每个查询只能过滤一个孩子。所以要么我们必须检索地球的整个纬度切片中的所有子项并过滤客户端我们必须找到一种方法将纬度和经度填充到单个保持美好的财产"它可以很容易地订购"数字属性。

      输入" Geohashes"和GeoFire。

      按Geohash过滤(使用Geofire)

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

      enter image description here

      来自移动设备的屏幕截图,因为我无法从桌面界面找到一个(无论如何它看起来非常相似)

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

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

        

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

           

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

           

      由于逐渐精确度降低,附近的地方通常会(但不总是)出现类似的前缀。共享前缀越长,两个位置越接近。

      这就像你的应用程序的秘密酱一样:geohash将纬度和经度编码为单个值,可以订购。我建议玩一下geohashes。由于原来的geohash.org似乎失败了,我使用了the Geohash service of openlocation.org。它甚至在白宫周围开始,并显示我们的位置在这些Geohashes周围的某处:// !!!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的工作人员也意识到这将非常有用,因此他们创建了一个名为Geofire的帮助库。有一个伟大的introduction and tutorial for GeoFire on Firebase's web site。我建议你继续在那里工作。