我用的MongoDB和的NodeJS(使用猫鼬)开始。
我有故事的集合,他们每个人都可以有一个或多个标签 ,这是类似的东西:
{
title: "The red fox",
content: "The red fox jumps away...",
tags: [
{
tagname: "fairytale",
user: "pippo"
},
{
tagname: "funny",
user: "pluto"
},
{
tagname: "fox",
user: "paperino"
}
]
},
... other stories
现在我想打一个标签云 。
它意味着查询所有标签的故事。
在一个关系世界(如MySQL的)我将有一个故事表,标签表和Stories_Tags表(很多到很多)。 然后我会在标签表或类似的东西查询。
有没有办法这样做呢? (我敢肯定是)
如果是的话,这是一个好的做法呢? 或者它打破了NoSQL的范式?
你能想象我的模式设计一个更好的办法?
您可以使用MR做到这一点。 在MR你只会挑选出标签和项目他们:
var map = function(){
for(var i=0;i<this.tags.length;i++){
emit(this.tags[i].tagname, {count: 1});
}
}
然后你的减少将通过发出的文件基本上总结的时候该标签被看作量运行。
如果升级到最新的的不稳定2.2,你也可以使用聚合框架。 你会使用聚合框架的$项目和$总和piplines到项目中的变量从每个岗位,然后总结起来,以创建一个基于分数标签云,让您的大小根据求和每个标签的文本。
如果是的话,这是一个好的做法呢? 或者它打破了NoSQL的范式?
这是MongoDB中一个非常标准的问题,一个你不会从脱身。 与可重复使用的结构而来的必然需要做一些复杂的查询了它。 幸运的是2.2存在aggregationm框架进行保存。
至于这是否是一个好的或坏的做法,这是一个非常标准的一个因此它既不是好还是坏。
至于使得结构更好,你可以预先骨料与他们的计数独特的标签,一个单独的集合。 这将使它更容易建立自己的标签云实时。
预聚合是创建其他集合,你通常会从MR获取,而无需使用抄表员或聚合框架的一种形式。 它通常是由事件根据您的应用程序,所以当用户创建一个帖子或retags后会触发一个预聚集事件“TAG_COUNT”,它看起来像一个集合:
{
_id: {},
tagname: "",
count: 1
}
当事件通过帖子上的标签触发了您的应用程序将循环基本上是做$ INC upserts像这样:
db.tag_count.update({tagname: 'whoop'}, {$inc: {count: 1}}, true);
所以你现在有标签的集合与整个博客的数量。 从那里,你走同样的路线为MR那样,只是查询该集合走出你的数据。 当然,您需要处理删除和更新事件,但你得到的总体思路。
这里是你如何做到这一点使用聚合框架(你需要使用刚刚发布2.2)。
db.stories.aggregate(
[
{
"$unwind" : "$tags"
},
{
"$group" : {
"_id" : "$tags.tagname",
"total" : {
"$sum" : 1
}
}
},
{
"$sort" : {
"total" : -1
}
}
])
你的结果会是这样的:
{
"result" : [
{
"_id" : "fairytale",
"total" : 3
},
{
"_id" : "funny",
"total" : 2
},
{
"_id" : "silly",
"total" : 1
},
{
"_id" : "fox",
"total" : 1
}
],
"ok" : 1
}
欢迎到蒙戈
最好的“架构”为您的数据将是这样的。
您创建一个名为故事集,每个故事都会成为这个集合中的文档。 然后,您可以轻松的东西,如查询数据。
db.stories.find({ "tags.tagname": "fairytale"}); // will find all documents that have fairytale as a tagname.
UPDATE
db.stories.find({ "tags.tagname": { $exists : true }}); // will find all documents that have a tagname.
注意在查找查询点符号,这就是你如何到达入蒙戈数组/对象。
那么,有不同的方式。 我认为这是您的解决方案,并没有什么区别这一个 。
,你也可以复制和粘贴其map_reduce方法输出标签数哈希值。