Firebase JS:startAt,orderByChild和limitToLast [英] Firebase js: startAt, orderByChild and limitToLast

查看:35
本文介绍了Firebase JS:startAt,orderByChild和limitToLast的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下查询以获取自上次提取以来的最新16篇文章:

I have the following query to get the newest 16 articles since the last fetch:

db.ref("articles).startAt(null, "last_fetched_key").orderByChild("published").limitToLast(16);

所以它应该从我写的最后一篇文章开始,然后按已发布"子键排序,然后将结果限制为16.

So it should start at the last article I have, then order those by the child key "published", then limit those results to 16.

只要我不执行orderByChild("published"),它就可以正常工作,但是如果我这样做,我总是可以获得16个项目?

It works as long as I don't do orderByChild("published") but if I do, I always get 16 items?

注意:我在nodejs(firebase-admin 5.1.0)和浏览器(firebase-sdk 4.2.0)上都看到了此行为

Note: I see this behavior on both nodejs (firebase-admin 5.1.0) and browser (firebase-sdk 4.2.0)

示例:(有关数据示例,请参见下文)

Example: (see below for data example)

function countObj(obj) { var c=0; for (var k in obj) { c++; } return c; }
function getLastKey(obj) { var lk=null; for (var k in obj) { lk = k; } return lk; }

firebase.database().ref("articles/-KnLhC7S0wtNV17R-w2I")
  .orderByChild("published")
  .limitToLast(4) // limit 4, 
  .once("value", function(snap) {

    var data = snap.val();

    console.log("#1 Results: "+ countObj(data.val())); // Results: 4

    var lastKey = getLastKey(data);

    // With .orderByChild("published")
    // Should return 1 result because articles contains 4, we pass the 4th key to startAt()
    firebase.database().ref("articles/-KnLhC7S0wtNV17R-w2I")
      .startAt(null, lastKey) // use startAt
      .orderByChild("published")
      .limitToLast(4)
      .once("value", function(snap) {
        var data = snap.val();
        console.log("#2 Results: "+ countObj(data.val())); // Results: 4
    });

    // Without .orderByChild("published")
    // Returns 1 result because articles contains 4, we pass the 4th key to startAt()
    firebase.database().ref("articles/-KnLhC7S0wtNV17R-w2I")
      .startAt(null, lastKey) // use startAt
      .limitToLast(4)
      .once("value", function(snap) {
        var data = snap.val();
        console.log("#3 Results: "+ countObj(data.val())); // Results: 1
    });


  });

数据:

{
  "articles" : {
    "-KnLhC7S0wtNV17R-w2I" : {
      "1498230632000-3M7VnZESptDyGP4iN6BXlNqi6ukG4HgWkX4KvwiWEKs%3D_15cd582aa38%3A50c8a%3A35f03cd7" : {
        "published" : 1498230632000
      },
      "1498230632001-3M7VnZESptDyGP4iN6BXlNqi6ukG4HgWkX4KvwiWEKs%3D_15cd582aa38%3A50c8a%3A35f03cd7" : {
        "published": 1000
      },
      "1498230632002-3M7VnZESptDyGP4iN6BXlNqi6ukG4HgWkX4KvwiWEKs%3D_15cd582aa38%3A50c8a%3A35f03cd7" : {
        "published": 900
      },
      "1498230632003-3M7VnZESptDyGP4iN6BXlNqi6ukG4HgWkX4KvwiWEKs%3D_15cd582aa38%3A50c8a%3A35f03cd7" : {
        "published": 1100
      },
    }
  }
}

推荐答案

您似乎误解了 startAt()的参数是如何工作的.这里有三个步骤:

You seem to misunderstand how the parameters for startAt() work. There are three steps here:

  1. 首先,按照查询的指示对数据进行排序.如果您未指定任何排序,则数据将按优先级排序(对于您的情况下的所有数据都是相同的)
  2. 查询然后找到第一个子项,其排序的值与您指定为第一个参数的子项匹配.
  3. 然后查询执行(可选)秒,并删除键之前的所有项目.

因此,在查询中,如果要在 1498230632003 ... 之后的下4个项目:

So in your query, if you want the next 4 items after 1498230632003...:

ref
  .orderByChild("published")
  .startAt(1100, "1498230632003-3M7VnZESptDyGP4iN6BXlNqi6ukG4HgWkX4KvwiWEKs%3D_15cd582aa38%3A50c8a%3A35f03cd7")
  .once("value", function(snap) {
    console.log("#2 Results: "+snap.numChildren()); // Results: 2
    snap.forEach(function(child) { 
      console.log(child.key); // 1498230632003..., 1498230632000...
    });
  });

如果要根据关键字确定从哪里开始查询结果,应使用 orderByKey():

If you want to determine where to start the query results based on the key, you should use orderByKey():

ref
  .orderByKey()
  .startAt("1498230632003-3M7VnZESptDyGP4iN6BXlNqi6ukG4HgWkX4KvwiWEKs%3D_15cd582aa38%3A50c8a%3A35f03cd7")
  .once("value", function(snap) {
  console.log("#2 Results: "+snap.numChildren()); // Results: 1
  snap.forEach(function(child) { 
    console.log(child.key); // 1498230632003...
  });
});

我不确定,但是似乎您正在尝试获取要对属性进行排序并对键进行过滤的查询.在Firebase数据库查询模型中,这是不可能的.有关您的选择,请参见 http://stackoverflow.com/questions/26700924/query-base-on-multiple-where-clauses-in-firebase

I'm not completely certain, but it seems like you're trying to get a query to order on a property and filter on the key too. This is not possible within the Firebase Database query model. For your options, see http://stackoverflow.com/questions/26700924/query-based-on-multiple-where-clauses-in-firebase

我要测试的jsbin: https://jsbin.com/xuwaxaq/edit?js,控制台

My jsbin for testing: https://jsbin.com/xuwaxaq/edit?js,console

您的代码中的一些代码片段很难理解.我建议用我更惯用的变体替换它们:

A few snippets from your code are hard to understand. I recommend replacing them with my more idiomatic variants:

countObj(data.val())

与以下相同:

snap.numChildren()

并且:

var lastKey = getLastKey(data);

与以下相同:

var lastKey;
snap.forEach(function(child) { lastKey = child.key; });

这篇关于Firebase JS:startAt,orderByChild和limitToLast的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆