【问题标题】:Firebase orderByChild() is not ordering numericallyFirebase orderByChild() 没有按数字排序
【发布时间】:2019-05-29 19:52:13
【问题描述】:

我正在尝试通过 Firebase 的 orderByChild() 查询方法对用户积分进行排序。我似乎无法完全理解它,因为我是 Typescript/Firebase 新手,所以我一直在使用很多示例代码。

我的 Firebase JSON 如下所示:

{
  "users" : {         
    "hJfEgXkyaKPckchL3kx8rpZ58Ew2" : {
      "-LV6c8E5rRD4_mQqsb6Q" : {
        "grade" : 11,
        "name" : "Lin Manuel Miranda",
        "points" : 100
      }
    },
    "mlIBrdjT8CfIURQEAhLFPzzUFQg1" : {
      "-LV7I6d8LeuWFLH5MRKy" : {
        "grade" : 12,
        "name" : "Emily Blunt",
        "points" : 20
      }
    }
 // "userID" : {
 //    "-firebase-generated-id": {
 //        "grade" : number,
 //        "name" : string,
 //        "points" : number
 //    }
 //  }
  }
}

我的代码虽然有点乱,但正在运行,因为我需要检索特定的键来引用数据库......所以,我试图将所有信息推送到一个新数组中,然后显示html里面的数组。

// ts file

export class Tab1Page {
  name: string;
  grade: number;
  points: number;
  empList: Array<{name: string, grade: number, points: number}> = [];

  constructor(
    private db: AngularFireDatabase
  ) {
        // the variable pkey here is a reference to the userID
        const keyRef = firebase.database().ref('/users/' + pkey);
        const ref2 = keyRef.orderByChild('points').limitToLast(7);

        ref2.once('value').then(function(snap2) {
          snap2.forEach(function (childSnap2) {
            const key = childSnap2.key;
            const List = this.empList;
            const firebaseRef = firebase.database().ref('/users/' + pkey + '/' + key);
            
            firebaseRef.once('value').then(function(snapshot) {
              const name = snapshot.val().name;
              const grade = snapshot.val().grade;
              const points = snapshot.val().points;
              List.push({
                name: name,
                grade: grade,
                points: points
              });
            });
          });
        });
      });
    });
  }

}

问题是,无论我如何编辑代码,orderByChild() 查询都会按照用户在数据库中的顺序返回我的用户,而不是按照他们的点值。

更新 对于那些将来可能也在为此苦苦挣扎的人,我修复它的方式(在弗兰克的帮助下)不是将用户 ID 设置为 JSON 路径的一部分,而是将 ID 推送为孩子之一:

{
  "users" : {
    "-LVL5EWo3MBnLdAv0fFf" : {
      "ID" : "g4V3ZmBRJfcN2WSeoSPuPbxl3o72",
      "grade" : 11,
      "name" : "Caroline Choi",
      "points" : 10
    },
    "-LVL69jiTxb5MprLpjrK" : {
      "ID" : "21XBQvWXtuayo1ZxxmS566phDv13",
      "grade" : 12,
      "name" : "Emily Blunt",
      "points" : 0
    }
  }
}

这使得查询可以正常运行。

【问题讨论】:

  • 您能否将代码缩减为单个查询(给您带来问题的查询)并仅记录键+分数?这样会更容易提供帮助。
  • @FrankvanPuffelen 嗨,弗兰克,我已经更新了代码(上图),但如果您希望我再减少一点,请告诉我。 “只记录键+分数”是什么意思?谢谢!
  • 我可能根本不明白你在做什么。您能否更新您的问题以包含您真实 JSON 的 sn-p(作为文本,没有屏幕截图),以便我自己尝试?您可以通过单击 Firebase Database console 的溢出菜单 (⠇) 中的“导出 JSON”链接来获取此信息。
  • 我现在添加了真正的 JSON。另外,因为我将我的代码最小化到只有令人不安的部分,让我解释一下我要去哪里。本质上,我需要获取用户 ID 和嵌套在用户 ID 下的东西的 ID 的引用,所以我运行了两次查询。
  • 当您将侦听器附加到某个位置时,您获得的快照包含该位置下的所有数据。据我所知,您不需要嵌套的侦听器。但是您的每个用户现在只有一个分数节点,那么我们如何才能看到特定用户的结果顺序不正确?

标签: typescript firebase ionic-framework firebase-realtime-database


【解决方案1】:

情况是您使用的是.once() 方法,而Firebase 实时查询仅适用于.on() 方法,如您在reference docs 中所见。因此,将使用 .orderByChild() 的引用更改为 .on() 应该可以正常工作。

另外,我建议您学习如何以更好的方式构建数据库,您的代码对于必须简单的东西来说非常复杂,并且您要对 Firebase 进行 3 次调用(或 3 级,因为有一个 forEach 有很多其他要求)。您必须考虑学习如何更好地使用 Firebase Realtime,否则您的代码将变得越来越难以进行维护和阅读。

希望这会有所帮助。

【讨论】:

  • "情况是您使用的是 .once() 方法,而 Firebase 实时查询仅适用于 .on() 方法" Firebase 查询在 on 和 @987654327 中的工作方式相同@。两者的唯一区别是once()在从数据库中获得第一个结果后会自动停止监听。
  • @GabrielBarreto 正如弗兰克指出的那样,我相信 .once() 的工作方式相同。是的,我的代码肯定需要更简单,但我还是个新手,无法真正弄清楚如何有效地减少它。
【解决方案2】:

由于我不确定问题出在哪里,所以我自己设置了一个小测试供您查看。

JSON:

{
  "-LV6c8E5rRD4_mQqsb6Q" : {
    "grade" : 11,
    "name" : "Lin Manuel Miranda",
    "points" : 100
  },
  "-LV6c8E5rRD4_mQqsb6Z" : {
    "grade" : 42,
    "name" : "Frank van Puffelen",
    "points" : 80
  }
}

实时 JSON:https://stackoverflow.firebaseio.com/54018652/users/hJfEgXkyaKPckchL3kx8rpZ58Ew2.json?print=pretty

代码:

var ref = firebase.database().ref("/54018652");

var keyRef = ref.child("users/hJfEgXkyaKPckchL3kx8rpZ58Ew2");
var ref2 = keyRef.orderByChild('points').limitToLast(7);

ref2.once('value').then(function(snap2) {
  snap2.forEach(function (childSnap2) {
    var key = childSnap2.key;
    var points = childSnap2.child("points").val();
    console.log(key+": "+points);
  });
});

工作代码:https://jsbin.com/ceyejil/edit?js,console

当我针对这个 JSON 运行这段代码时,它会打印:

-LV6c8E5rRD4_mQqsb6Z:80

-LV6c8E5rRD4_mQqsb6Q:100

所以这些是我正在查询的位置下的两个节点,按照它们的点值的顺序。

【讨论】:

  • 弗兰克,我将您的回复标记为答案,因为它帮助我理解了为什么我的代码不起作用。此外,我更新了我的问题以反映我如何修改我的 JSON 以匹配您的(以及查询如何完美地工作)。谢谢!
  • 很高兴听到卡罗琳。
猜你喜欢
  • 2016-03-08
  • 2017-09-22
  • 1970-01-01
  • 1970-01-01
  • 2017-08-22
  • 2020-12-26
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多