首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >数据库和搜索专家:对多值字段的加权分面搜索

数据库和搜索专家:对多值字段的加权分面搜索
EN

Stack Overflow用户
提问于 2013-03-21 16:05:08
回答 1查看 307关注 0票数 1

这个问题几乎可以归结为“多方面的搜索,多个多值字段,按权重而不是计数排序”。

数据库

我有大约1000万个事件,每个事件都有多个版本,每个版本都是用标签来描述的。有5种标签类型(地点,演讲者,参与者,主题,行业)。

代码语言:javascript
运行
复制
{
    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: [ ... ] 
        }
    ]
}

数据逻辑

  • 标签是分层的,例如,“埃里克·施密特”是在谷歌下注册的,而“埃里克·施密特”则是在科技公司下注册的。因此,无论何时Eric在一个事件中,所有三个标记都与事件相关联。
  • 不同的标签可能有不同的流行度,这意味着“埃里克·施密特”的流行度为100,而“艾琳·诺顿”的流行度为"10“。
  • 受欢迎程度不适用于层次结构。这意味着,如果“埃里克·施密特”(Eric)离开谷歌前往Foursquare,他的人气仍将是100,而Foursquare仍有50 %的人气。
  • 如果在给定的时间,我们发现另一个“参与者”出席了,例如,我们需要能够添加他作为一个标签。

搜索要求

现在,想象一下左边的菜单有四个部分:

代码语言:javascript
运行
复制
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溶液

为每个版本存储一个单独的文档:

代码语言:javascript
运行
复制
{
    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个查询)*

代码语言:javascript
运行
复制
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万个事件版本,每个版本都有数千个可能的标记。

有人能想到另一种方法吗?除了使用“映射/减少”之外,这个方法还能被优化吗?我知道,对于每个用户来说,这种方法太慢了,无法实时执行吗?

EN

回答 1

Stack Overflow用户

发布于 2015-04-14 07:00:16

根据您的搜索需要如何“生活”,您是否考虑过使用增量映射/减少?

http://docs.mongodb.org/manual/tutorial/perform-incremental-map-reduce/

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15552515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档