我正在尝试为Firebase应用程序设计高性能的NoSQL架构,但我如何查询具有唯一标记的多个检查点?
请考虑以下规则:
这是我到目前为止所拥有的:
{
"tiers": {
"1": {
"web": true,
"android": true
},
"2": {
"basics": true,
"angular2": true,
"aurelia": true
},
"3": {
"basics": true,
"components": true
}
},
"tags" : {
"1": {
"web": {
"name": "Web Development",
"children": {
"front-end": true,
"angular2": true,
"aurelia": true
}
},
"android": {
"name": "Android Development",
"children": {
"front-end": true
}
}
},
"2": {
"front-end": {
"name": "Basics",
"parents": {
"web": true,
"android": true
},
"children": {
"angular2": true,
"aurelia": true,
"android-studio": true
}
}
},
"3": {
"angular2": {
"name": "Angular 2.x",
"parents": {...},
"children": {...}
},
"aurelia": {
"name": "Aurelia 1.x"
}
}
},
"checkpoints": {
"<randomKey>" : {
"name": "Angular 2 Quick Start",
"tags": {
"1": "web",
"2": "front-end",
"3": "angular2"
}
}
}
}
现在,我可以在第1层web
标记下查询所有检查点:
ref.orderByChild('tags/1').equalTo("web").once('value', snap => console.log(snap.val()));
但由于您只能定义一个indexOn
规则,因此未对其进行优化。至少如果我可以设置indexOn
规则,我至少可以过滤掉大部分检查点,然后在我的代码中过滤掉其余部分。
如何根据多个tags
和tiers
最终,我需要使用checkpoints
对"tags": {"1": "web" AND "2": "front-end"}
进行查询,但我无法确定如何有效执行。我正在考虑使用复合键执行另一个表(例如,每个tier/tag
包含对所有子checkpoints
的引用),但这会导致我要求在每个层中添加和删除引用。
必须有更好的方法。
答案 0 :(得分:0)
我大大超过了解决方案 - 我最终:
Tier
这是我的新架构:
allTags = [
{"abc": true, "def": true, "hij": true},
{"abc": true, "def": true}
];
tags: [
{ "0": [
{"software-development": {name: "Software Development", checkpoints: [ {"abc": true}, {"def": true}, {"hij": true}]}}
]},
{"1": [
{"web": {name: "Web", checkpoints: [ {"abc": true}, {"def": true}]}},
{"android": {name: "Android", checkpoints: [{"hij": true}]}}
]}
];
checkpoints: [
{"abc": { name: "Angular2 Quick Start"}},
{"def": { name: "Building global directives in Angular2"}},
{"hij": { name: "Android Quick Start"}},
];
创建新的检查点:
public createCheckpoint(tags: any[], checkpoint: any) {
// push checkpoint
let checkpointRef = this.firebase.child('test/checkpoints');
let checkpointKey = checkpointRef.push(checkpoint).key(); // might have to do separate call
// Add checkpoint under each related tag
tags.forEach(tag => {
let tagRef = this.firebase.child('test/tags/' + tag.tier + '/' + tag.key + '/checkpoints/' + checkpointKey);
tagRef.set(true)
});
}
根据所选标签检索所有检查点:
public getCheckpointss(tags: any[]) {
// tag.tier, tag.key
let checkpointKeysToGet: string[] = [];
tags.forEach(tag => {
let ref = this.firebase.child('test/tags/' + tag.tier + '/' + tag.key + '/checkpoints');
ref.once('value', snap => {
let tagKeys:string[] = this.convertToArray(snap.val());
if (checkpointKeysToGet.length == 0){
checkpointKeysToGet = checkpointKeysToGet.concat(tagKeys);
}
else {
checkpointKeysToGet.forEach(existingTagKey => {
let tagKeysInBothTiers = tagKeys.filter(tagKey => {
return checkpointKeysToGet.includes(tagKey, 0)
});
checkpointKeysToGet = tagKeysInBothTiers;
console.log(checkpointKeysToGet);
});
}
});
});
}
只要您提出解决方案,我们欢迎所有有效的批评:)