这个问题几乎可以归结为“多方面的搜索,多个多值字段,按权重而不是计数排序”。
数据库
我有大约1000万个事件,每个事件都有多个版本,每个版本都是用标签来描述的。有5种标签类型(地点,演讲者,参与者,主题,行业)。
{
title: "CES",
editions: [
{
date: "2013-02-01",
tags: [ {label: "Eric Schmidt", type: "speaker", "popularity": 50}, {label: "Paris", type: "place", "popularity": 30} ]
},
{
date: "2012-01-23",
tags: [ ... ]
}
]
}
数据逻辑
搜索要求
现在,想象一下左边的菜单有四个部分:
Places
------------
Paris
London
New York
[more]
Speakers
----------
Google
Facebook
Marc Zuckerberg
[more]
诸若此类。
每当用户单击标签时,我希望菜单能够反映结果,并允许他进一步深入(分面搜索)。扭转之处在于,当决定在每个部分的前三个标签中显示"Google“与"Eric Schmidt”和"Foursquare“时,我想根据匹配事件的数量*标记受欢迎程度来确保最受欢迎的标签显示得更高。这意味着,如果" Foursquare“有3个匹配事件,而"Eric”只有一个匹配事件,那么应该首先显示Foursquare,得分为3*50 = 150,而Schmidt的分数为1* 100。
另外,理想的情况是,如果我选择" Google“,那么,对于”扬声器“部分,系统不应该返回Google之外的扬声器,即使匹配的事件也有”扎克伯格“的列表,具有巨大的人气200。因此,返回的标记应该驻留在每个部分中当前选择的“下面”,并且它们的排序应该基于上述评分逻辑。
电流MongoDB溶液
为每个版本存储一个单独的文档:
{
event: "CES",
date: "2013-02-01",
tags: [ {label: "Eric Schmidt", type: "speaker", "popularity": 50, path: ",Tech Companies,Google,"}, {label: "Paris", type: "place", "popularity": 30, path: ",Europe,France,"} ]
},
{
event: "CES",
date: "2012-01-23",
tags: [ ... ]
}
使用聚合框架
*每个标签类型一个查询(每个请求5个查询)*
db.events.aggregate(
{
'$match': {'tags.label': {'$all': ["selected tag 1", "selected tag2", ...]}}
},
{
'$unwind': '$tags'
},
// group by events, so we can later sum each tag's popularity only once per event, not per event edition
{
'$group': {
'_id': '$event',
'taglistUnqiue': {
'$addToSet': {
'label': '$tags.label',
'type': '$tags.type',
'popularity': '$tags.popularity'
}
}
}
},
{
'$unwind': '$taglist'
},
{
'$match': {
'taglist.type': "speaker",
/* haven't tested this path-matching, but it should work
to only get the tags that are in the bottom tree
of the current selected speaker tag */
'taglist.path': /^,selected speaker tag,/,
}
},
{
'$group': {
'_id': '$taglist.label',
'score': {
'$sum': '$taglist.popularity'
}
}
});
好的,从算法上来说,这应该是可行的,但是从性能上来说,它肯定不会适用于5000万个事件版本,每个版本都有数千个可能的标记。
有人能想到另一种方法吗?除了使用“映射/减少”之外,这个方法还能被优化吗?我知道,对于每个用户来说,这种方法太慢了,无法实时执行吗?
发布于 2015-04-14 07:00:16
根据您的搜索需要如何“生活”,您是否考虑过使用增量映射/减少?
http://docs.mongodb.org/manual/tutorial/perform-incremental-map-reduce/
https://stackoverflow.com/questions/15552515
复制相似问题