我想为我的用户提供一个API(指向我的服务器),它将从Firebase获取数据并将其返回给他们。我希望它是一个正常的'时间点请求(与流式传输相反)。
我的数据是'框'在'项目'。用户可以查询我的API以获取项目的所有框。
我的数据已标准化,因此我将查找项目并获取该项目中框的键列表,然后单独获取每个框记录。一旦我拥有它们,我将把数组返回给用户。
我的问题:最好的方法是什么?
这是我拥有的,而且有效。但它感觉太乱了。
const projectId = req.params.projectId; // this is passed in by the user in their call to my server.
const boxes = [];
let totalBoxCount = 0;
let fetchedBoxCount = 0;
const projectBoxesRef = db
.child('data/projects')
.child(projectId)
.child('boxes'); // a list of box keys
function getBox(boxSnapshot) {
totalBoxCount++;
db
.child('data/boxes') // a list of box objects
.child(boxSnapshot.key())
.once('value')
.then(boxSnapshot => {
boxes.push(boxSnapshot.val());
fetchedBoxCount++;
if (fetchedBoxCount === totalBoxCount) {
res.json(boxes); // leap of faith that getBox() has been called for all boxes
}
});
}
projectBoxesRef.on('child_added', getBox);
// 'value' fires after all initial 'child_added' things are done
projectBoxesRef.once('value', () => {
projectBoxesRef.off('child_added', getBox);
});
关于分离初始child_added
个对象的问题还有一些其他问题/答案,它们影响了我当前的决定,但它们似乎并没有直接相关。
感谢卡车装载任何帮助。
更新:Jay的答案的JavaScript版本如下:
db
.child('data/boxes')
.orderByChild(`projects/${projectId}`)
.equalTo(true)
.once('value', boxSnapshot => {
const result = // some parsing of response
res.json(result);
});
答案 0 :(得分:1)
这可能是一个简单的解决方案,但如果您有项目,并且每个项目都有框
您的项目节点
projects
project_01
boxes
box_id_7: true
box_id_9: true
box_id_34: true
project_37
boxes
box_id_7: true
box_id_14: true
box_id_42: true
和框节点
boxes
box_id_7
name: "a 3D box"
shape: "Parallelepiped"
belongs_to_project
project_01: true
box_id_14
name: "I have unequal lenghts"
shape: "Rhumboid"
belongs_to_project
project_37: true
box_id_34
name: "Kinda like a box but with rectangles"
shape: "cuboid"
belongs_to_project
project_01: true
这样,在box节点上只有一个(深度)查询将加载属于project_01的所有框,在本例中为box_id_7和box_id_34。
您可以采用另一种方式,因为您知道项目节点中每个项目的框ID,您可以通过它的特定路径/ box / box_id_7等执行一系列观察者来加载每个项目。我更喜欢这个问题;更快,更少的带宽。
如果一个方框可以属于多个项目,你可以对此进行扩展:
box_id_14
name: "I have unequal lenghts"
shape: "Rhumboid"
belongs_to_project
project_01: true
project_37: true
现在在框节点上查询属于project_01的所有框将获得box_id_7,box_id_14和box_id_34。
编辑:
一旦该结构到位,使用深度查询然后获取属于相关项目的框。
例如:假设您要制作一个Firebase Deep Query来返回框中所属的框__ project_toject列表包含一个带有键的项目" project_37"
boxesRef.queryOrderedByChild("belongs_to_project/project_37"
.queryEqualToValue(true)
.observeSingleEventOfType(.Value, withBlock: { snapshot in
print(snapshot)
})
答案 1 :(得分:0)
好的,我觉得我对我的方法感到满意,一旦所有单个“查询”都被返回,使用Promise.all
回复:
我改变了使用promises的方法,然后调用Promise.all()
表示所有数据都已准备好发送。
const projectId = req.params.projectId;
const boxPromises = [];
const projectBoxesRef = db
.child('data/projects')
.child(projectId)
.child('boxes');
function getBox(boxSnapshot) {
boxPromises.push(db
.child('data/boxes')
.child(boxSnapshot.key())
.once('value')
.then(boxSnapshot => boxSnapshot.val())
);
}
projectBoxesRef.on('child_added', getBox);
projectBoxesRef.once('value', () => {
projectBoxesRef.off('child_added', getBox);
Promise.all(boxPromises).then(boxes => res.json(boxes));
});