Firebase 嵌套查询
Firebase Nested Query
我是 firebase 的新手并且已经通读了文档,但似乎无法找到一个方法来获取所有填充了用户数据的阶梯的列表。我真的不想在他们所属的每个阶梯中复制用户数据。
这是我的数据结构:
{
"ladders" : [ {
"description" : "Real Real Tennis",
"name" : "Ping Pong",
"players" : {
"simplelogin:5" : true
}
}, {
"description" : "Real Tennis",
"name" : "Mario Tennis",
"players" : {
"simplelogin:5" : true
}
} ],
"users" : {
"simplelogin:5" : {
"email" : "bob@bob.com",
"md5hash" : "1e737a7b6e1f0afb1d6fef521097400b",
"name" : "Bob",
"username" : "bob1"
}
}
}
这是我最好的尝试,但看起来梯子查找已经完成,returns 在用户查找完成之前,所以 returns 玩家是空的。
laddersRef.on('value', function(laddersSnapShot){
var ladders = []
laddersSnapShot.forEach(function(ladderData) {
var ladder = ladderData.val();
ladder.players = [];
ladder.id = ladderData.key();
laddersRef.child(ladder.id).child('players').on('value', function(snap){
snap.forEach(function(player){
usersRef.child(player.key()).on('value', function(snap1){
ladder.players.push(snap1.val())
})
})
})
ladders.push(ladder)
});
});
关于此示例的大部分内容都已损坏。在以有意义的方式回答这个问题之前,通读 the guide 是必不可少的。如所写,您的代码会在任何时候在梯子中的任何地方的任何字段/被修改时在每个梯子的玩家列表上建立一个新的侦听器。
发生这种情况是因为 laddersRef.on('value') 将在该路径中的任何位置发生更改时随时更新。每次发生这种情况时,您都会建立 laddersRef.child(ladder.id).child('players').on('value'),这会在每个阶梯的玩家/路径上创建多个侦听器。 retrieving data
中介绍了其基本原理
这里的正确答案是按预期使用这些工具,而不是试图通过异步 API 方法进行缓慢、乏味、容易出错的同步过程。
要直接回答你的问题,这就是你要求的:
function done(ladders) {
console.log(ladders);
}
laddersRef.on('value', function(laddersSnapShot){
function doneWithLadder() {
if( ++laddersDone === laddersNeeded ) {
done(ladders);
}
}
var ladders = [];
var laddersDone = 0;
var laddersNeeded = laddersSnapShot.numChildren();
laddersSnapShot.forEach(function(ladderData) {
var ladder = ladderData.val();
var playersFound = 0;
var playersNeeded = ladderData.numChildren();
ladder.players = [];
ladder.id = ladderData.key();
laddersSnapshot.child('players').forEach(function(ps) {
usersRef.child(ps.key()).once('value', function(userSnap) {
ladder.players.push(usersSnap.val());
if( ++playersFound === playersNeeded ) {
doneWithLadder();
}
});
});
});
});
但这更优雅(更优雅的是使用框架并完全避免这种情况):
function addLadder(snap) {
putLadderInDom(snap.key(), snap.val());
snap.ref().child('players').on('value', changePlayers);
// Use whatever framework you have available to put this into
// the DOM. Be sure to keep the record key around so you can
// add the user in later
}
function changePlayers(playersSnap) {
var ladderKey = playersSnap.parent().key();
var numFetched = 0;
var numPlayersToFetch = playersSnap.numChildren();
var profiles = {};
playersSnap.forEach(function(ss) {
loadProfile(ss.key(), function(userSnap) {
profiles[userSnap.key()] = userSnap.val();
if( ++numFetched === numPlayersToFetch ) {
updatePlayers(ladderKey, profiles);
}
});
});
}
function updatePlayers(ladderKey, profiles) {
// use whatever framework you have available to insert profiles
// into the DOM
}
function loadProfile(key, callback) {
usersRef.child(key).once('value', callback);
}
laddersRef.on('child_added', addLadder);
我是 firebase 的新手并且已经通读了文档,但似乎无法找到一个方法来获取所有填充了用户数据的阶梯的列表。我真的不想在他们所属的每个阶梯中复制用户数据。
这是我的数据结构:
{
"ladders" : [ {
"description" : "Real Real Tennis",
"name" : "Ping Pong",
"players" : {
"simplelogin:5" : true
}
}, {
"description" : "Real Tennis",
"name" : "Mario Tennis",
"players" : {
"simplelogin:5" : true
}
} ],
"users" : {
"simplelogin:5" : {
"email" : "bob@bob.com",
"md5hash" : "1e737a7b6e1f0afb1d6fef521097400b",
"name" : "Bob",
"username" : "bob1"
}
}
}
这是我最好的尝试,但看起来梯子查找已经完成,returns 在用户查找完成之前,所以 returns 玩家是空的。
laddersRef.on('value', function(laddersSnapShot){
var ladders = []
laddersSnapShot.forEach(function(ladderData) {
var ladder = ladderData.val();
ladder.players = [];
ladder.id = ladderData.key();
laddersRef.child(ladder.id).child('players').on('value', function(snap){
snap.forEach(function(player){
usersRef.child(player.key()).on('value', function(snap1){
ladder.players.push(snap1.val())
})
})
})
ladders.push(ladder)
});
});
关于此示例的大部分内容都已损坏。在以有意义的方式回答这个问题之前,通读 the guide 是必不可少的。如所写,您的代码会在任何时候在梯子中的任何地方的任何字段/被修改时在每个梯子的玩家列表上建立一个新的侦听器。
发生这种情况是因为 laddersRef.on('value') 将在该路径中的任何位置发生更改时随时更新。每次发生这种情况时,您都会建立 laddersRef.child(ladder.id).child('players').on('value'),这会在每个阶梯的玩家/路径上创建多个侦听器。 retrieving data
中介绍了其基本原理这里的正确答案是按预期使用这些工具,而不是试图通过异步 API 方法进行缓慢、乏味、容易出错的同步过程。
要直接回答你的问题,这就是你要求的:
function done(ladders) {
console.log(ladders);
}
laddersRef.on('value', function(laddersSnapShot){
function doneWithLadder() {
if( ++laddersDone === laddersNeeded ) {
done(ladders);
}
}
var ladders = [];
var laddersDone = 0;
var laddersNeeded = laddersSnapShot.numChildren();
laddersSnapShot.forEach(function(ladderData) {
var ladder = ladderData.val();
var playersFound = 0;
var playersNeeded = ladderData.numChildren();
ladder.players = [];
ladder.id = ladderData.key();
laddersSnapshot.child('players').forEach(function(ps) {
usersRef.child(ps.key()).once('value', function(userSnap) {
ladder.players.push(usersSnap.val());
if( ++playersFound === playersNeeded ) {
doneWithLadder();
}
});
});
});
});
但这更优雅(更优雅的是使用框架并完全避免这种情况):
function addLadder(snap) {
putLadderInDom(snap.key(), snap.val());
snap.ref().child('players').on('value', changePlayers);
// Use whatever framework you have available to put this into
// the DOM. Be sure to keep the record key around so you can
// add the user in later
}
function changePlayers(playersSnap) {
var ladderKey = playersSnap.parent().key();
var numFetched = 0;
var numPlayersToFetch = playersSnap.numChildren();
var profiles = {};
playersSnap.forEach(function(ss) {
loadProfile(ss.key(), function(userSnap) {
profiles[userSnap.key()] = userSnap.val();
if( ++numFetched === numPlayersToFetch ) {
updatePlayers(ladderKey, profiles);
}
});
});
}
function updatePlayers(ladderKey, profiles) {
// use whatever framework you have available to insert profiles
// into the DOM
}
function loadProfile(key, callback) {
usersRef.child(key).once('value', callback);
}
laddersRef.on('child_added', addLadder);