【问题标题】:Firebase js: startAt, orderByChild and limitToLastFirebase js:startAt、orderByChild 和 limitToLast
【发布时间】:2017-08-12 10:52:10
【问题描述】:

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

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

所以它应该从我的最后一篇文章开始,然后按子键“已发布”对它们进行排序,然后将这些结果限制为 16 个。

只要我不做 orderByChild("published") 它就可以工作,但如果我做了,我总是会得到 16 件物品?

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

示例:(数据示例见下文)

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
      },
    }
  }
}

【问题讨论】:

  • 请分享重现问题所需的最小 JSON(以文本形式,无屏幕截图)。您可以通过单击Firebase Database console 中的“导出 JSON”链接来获取此信息。
  • 完成! (我希望我的示例代码足够清楚.. 在这里输入所以没有检查.. :))

标签: javascript firebase firebase-realtime-database


【解决方案1】:

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

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

所以在您的查询中,如果您想要 1498230632003... 之后的下 4 个项目:

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

如果要根据key确定从哪里开始查询结果,应该使用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-based-on-multiple-where-clauses-in-firebase

我用于测试的 jsbin:https://jsbin.com/xuwaxaq/edit?js,console

您的代码中的一些 sn-ps 很难理解。我建议用我更惯用的变体替换它们:

countObj(data.val())

等同于:

snap.numChildren()

还有:

var lastKey = getLastKey(data);

等同于:

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

【讨论】:

  • 谢谢,我会试一试,并在确定我理解后立即标记为已回答:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-09
  • 1970-01-01
  • 2017-08-22
  • 2020-12-26
  • 1970-01-01
相关资源
最近更新 更多