火力地堡使许多人反规范化 [英] Firebase denormalizing many to many
问题描述
我有一个非常基本的数据结构
I have a pretty basic data structure
- 事件
- 主题
我希望能够轻松显示(查询)
I would like to be able to easily show (query)
-
事件拥有什么主题
what topics are owned by an event
涉及主题的事件
本月最受欢迎的主题
我对自己的事件结构很满意
I am pretty comfortable with my events structure like
/events/880088/topics.json *
["Firebase", "Cloud"]
但是我在如何构造/topics节点上很费劲.我部分地想到了使用
but I struggle with how to structure the /topics nodes. I partially get the idea of going with something like
/topics/Firebase
{"12345":true,"88088":true}
,然后,如果我更新事件的主题集合,则必须遍历所有/topics/节点并将/topics/{{topic}}/{{eventid}} 更新为{真实|空值}.似乎很伤脑筋.
and then if when I update an events's topic collection I would have to iterate over all the /topics/ nodes and update /topics/{{topic}}/{{eventid}} to {true | null}. Which seems rather ham fisted.
ALSO,那么我仍然不知道如何查询本月活动的主题.
ALSO, then I am still at a loss of how to query say, what are the topics covered by events this month.
示例JSBin,来自以下注释 http://jsbin.com/dumumu/edit?js,output
Example JSBin from comments below http://jsbin.com/dumumu/edit?js,output
*
I know, I know, arrays are evil, https://www.firebase.com/blog/2014-04-28-best-practices-arrays-in-firebase.html, but I think they fit in this scenaris
推荐答案
以下是添加事件的一种方法:
Here's one way to add an event:
function addEvent(title, topics) {
var event =ref.child('events').push({ title: title });
topics.forEach(function(topic) {
event.child('topics').child(topic).set(true);
ref.child('topics').child(topic).child(event.key()).set(true);
});
}
对我来说似乎很简单.有趣的是,您可以使用新的我们昨天发布的多位置更新(2015年9月):
Seems pretty simple for me. For an interesting twist, you can use the new multi-location updates we launched yesterday (September 2015):
function addEvent(title, topics) {
var updates = {};
var eventId = ref.push().key();
updates['events/'+eventId+'/title'] = title;
topics.forEach(function(topic) {
updates['events/'+eventId+'/topics/'+topic] = true;
updates['topic/'+topic+'/'+eventId] = true;
});
ref.update(updates);
}
后者是更多代码.但这只是对Firebase的一次写入操作,因此用户没有机会在两次写入操作之间关闭应用程序.
The latter is a bit more code. But it's a single write operation to Firebase, so there's no chance of the user closing the app between write operations.
您当然可以同时调用这两者:
You invoke both the same of course:
addEvent('Learn all about Firebase', ['Firebase']);
addEvent('Cloudspin', ['Firebase', 'Google', 'Cloud']);
数据结构变为:
{
"events": {
"-K-4HCzj_ziHkZq3Fpat": {
"title": "Learn all about Firebase",
"topics": {
"Firebase": true
}
},
"-K-4HCzlBFDIwaA8Ajb7": {
"title": "Cloudspin",
"topics": {
"Cloud": true,
"Firebase": true,
"Google": true
}
}
},
"topic": {
"Cloud": {
"-K-4HCzlBFDIwaA8Ajb7": true
},
"Firebase": {
"-K-4HCzj_ziHkZq3Fpat": true,
"-K-4HCzlBFDIwaA8Ajb7": true
},
"Google": {
"-K-4HCzlBFDIwaA8Ajb7": true
}
}
}
查询/报告
使用Firebase(和大多数NoSQL数据库),通常必须调整数据结构以适合您要在其上进行的报告.
Querying/reporting
With Firebase (and most NoSQL databases), you typically have to adapt your data structure for the reporting you want to do on it.
安倍晋三在此问题上写了一个很好的答案,因此请务必阅读以下内容: Firebase数据结构必需的建议
Abe wrote a great answer on this recently, so go read that for sure: Firebase Data Structure Advice Required
如果您想更改现有事件的主题,此功能是完成此任务的一种方法:
If you want to change the topics for an existing event, this function is once way to accomplish that:
function updateEventTopics(event, newTopics) {
newTopics.sort();
var eventId = event.key();
var updates = {};
event.once('value', function(snapshot) {
var oldTopics = Object.keys(snapshot.val().topics).sort();
var added = newTopics.filter(function(t) { return oldTopics.indexOf(t) < 0; }),
removed = oldTopics.filter(function(t) { return newTopics.indexOf(t) < 0; });
added.forEach(function(topic) {
updates['events/'+eventId+'/topics/'+topic] = true;
updates['topic/'+topic+'/'+eventId] = true;
});
removed.forEach(function(topic) {
updates['events/'+eventId+'/topics/'+topic] = null;
updates['topic/'+topic+'/'+eventId] = null;
});
ref.update(updates);
});
}
The code is indeed a bit long, but that's mostly to determine the delta between the current topics and the new topics.
如果您好奇的话,如果我们现在运行这些API调用:
In case you're curious, if we run these API calls now:
var event = addEvent('Cloudspin', Date.now() - month, ['Firebase', 'Google', 'Cloud']);
updateEventTopics(event, ['Firebase', 'Google', 'GCP']);
changeEventTopics()
调用将导致此 update()
:
{
"events/-K-93CxuCrFDxM6k0B14/topics/Cloud": null,
"events/-K-93CxuCrFDxM6k0B14/topics/GCP": true,
"topic/Cloud/-K-93CxuCrFDxM6k0B14": null,
"topic/GCP/-K-93CxuCrFDxM6k0B14": true
}
这篇关于火力地堡使许多人反规范化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!