Firebase按嵌套子节点name字段字母排序问题排查
问题分析与解决方案
你遇到的核心问题是:Firebase实时数据库的查询排序结果,在转换成普通JavaScript对象后会丢失排序信息。
为什么orderByChild('name')没生效?
当你调用orderByChild('name')时,Firebase确实已经在服务器端完成了排序,但你用的kap.firebase.bindings.liveObject应该是把查询快照直接转换成了普通JS对象。而JavaScript对象的键是不保证维持查询排序顺序的(即使现代浏览器会保留插入顺序,也和Firebase的查询排序逻辑无关),所以你看到的还是Firebase默认的节点顺序。
两种可行的解决方法
方法1:直接处理Firebase快照,获取有序数组
修改你的getSensors函数,放弃liveObject绑定,手动从快照中提取有序的数据:
getSensors: function(uid, event_id, success){ var ref=firebase.database().ref('clients_events_sensors/'+ uid+ '/'+ event_id).orderByChild('name'); // 监听value事件,直接处理快照 ref.on('value', function(snapshot) { const sortedSensors = []; // snapshot.forEach会严格按照查询的排序顺序遍历子节点 snapshot.forEach(function(childSnapshot) { const sensor = childSnapshot.val(); sensor.key = childSnapshot.key; // 保留原节点的key(如果后续需要用到) sortedSensors.push(sensor); }); success(sortedSensors); }, function(e){ kap.log('cant get client event sensors', e) }); },
然后调用时直接遍历数组(顺序已经是按name排序好的):
app.data.getSensors(kap.page.uid, kap.page.event_id, function(sensors) { sensors.forEach(function(sensor){ sensor.photo = null; sensor.total = Math.round((sensor.in+sensor.out) / 2); sensor.sum = sensor.in+sensor.out; }); kap.log('got sensors', sensors); kap.page.sensors = sensors; kap.page.fill(); });
方法2:保留现有逻辑,拿到对象后手动排序数组
如果不想修改getSensors的底层实现,可以在回调中把普通对象转换成数组,再按name字段排序:
app.data.getSensors(kap.page.uid, kap.page.event_id, function(sensors) { // 把对象转成包含key和值的数组 const sensorsArray = Object.entries(sensors).map(([key, sensor]) => ({ ...sensor, key: key })); // 按name字段进行字母排序 sensorsArray.sort((a, b) => a.name.localeCompare(b.name)); // 后续处理逻辑不变 sensorsArray.forEach(function(sensor){ sensor.photo = null; sensor.total = Math.round((sensor.in+sensor.out) / 2); sensor.sum = sensor.in+sensor.out; }); kap.log('got sensors', sensorsArray); kap.page.sensors = sensorsArray; kap.page.fill(); });
内容的提问来源于stack exchange,提问作者Yoann Hercouet
相关产品推荐
相关产品推荐

