Fab*_* B. 8 tags many-to-many mongoose mongodb nosql
我开始使用MongoDb和nodejs(使用mongoose).
我有一个故事集合,每个都可以有一个或多个标签,它是这样的:
{
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
Run Code Online (Sandbox Code Playgroud)
现在我想做一个标签云.
这意味着查询所有标签的故事.
在关系世界(例如MySQL)中,我会有一个Stories表,一个Tags表和一个Stories_Tags表(多对多).然后我会在标签表或类似的东西上查询.
有办法吗?(我确定是的)
如果是的话,这是一个好习惯吗?还是它打破了nosql范式?
你能想象出我的架构设计有更好的方法吗?
Asy*_*sky 10
以下是使用聚合框架执行此操作的方法(您需要使用刚刚发布的2.2).
db.stories.aggregate(
[
{
"$unwind" : "$tags"
},
{
"$group" : {
"_id" : "$tags.tagname",
"total" : {
"$sum" : 1
}
}
},
{
"$sort" : {
"total" : -1
}
}
])
Run Code Online (Sandbox Code Playgroud)
您的结果将如下所示:
{
"result" : [
{
"_id" : "fairytale",
"total" : 3
},
{
"_id" : "funny",
"total" : 2
},
{
"_id" : "silly",
"total" : 1
},
{
"_id" : "fox",
"total" : 1
}
],
"ok" : 1
}
Run Code Online (Sandbox Code Playgroud)
您可以使用 MR 来完成此任务。在 MR 中,您只需挑选标签并投影它们:
var map = function(){
for(var i=0;i<this.tags.length;i++){
emit(this.tags[i].tagname, {count: 1});
}
}
Run Code Online (Sandbox Code Playgroud)
然后你的reduce将遍历发出的文档,基本上总结出该标签被看到的次数。
如果你升级到最新的unstable 2.2,你还可以使用聚合框架。您将使用聚合框架的 $project 和 $sum 管道将标签从每个帖子中投影出来,然后将它们相加以创建基于分数的标签云,从而允许您根据求和来调整每个标签的文本大小。
如果是,这是一个好的做法吗?或者它打破了 nosql 范式?
这是 MongoDB 中一个相当标准的问题,也是一个你无法回避的问题。随着可重用结构的出现,不可避免地需要对其进行一些复杂的查询。幸运的是,2.2 中有 AggregationM 框架可以保存。
至于这是好还是坏方法,这是一个相当标准的方法,因此既不好也不坏。
为了使结构更好,您可以将独特的标签及其计数预先聚合到一个单独的集合中。这将使实时构建标签云变得更加容易。
预聚合是创建通常从 MR 获得的其他集合的一种形式,无需使用 MR 或聚合框架。它通常是基于您的应用程序的事件,因此当用户创建帖子或重新标记帖子时,它将触发“tag_count”集合的预聚合事件,如下所示:
{
_id: {},
tagname: "",
count: 1
}
Run Code Online (Sandbox Code Playgroud)
当事件被触发时,您的应用程序将循环浏览帖子上的标签,基本上执行 $inc 更新插入,如下所示:
db.tag_count.update({tagname: 'whoop'}, {$inc: {count: 1}}, true);
Run Code Online (Sandbox Code Playgroud)
因此,您现在将拥有整个博客中的标签集合及其计数。从那里你可以走与 MR 相同的路线,只需查询这个集合即可获取你的数据。您当然需要处理删除和更新事件,但您已经了解了总体思路。
| 归档时间: |
|
| 查看次数: |
5283 次 |
| 最近记录: |