2014-09-29 91 views
0

我有一个非常大的集合(超过800k),我需要实现基于标签的自动完成(基于单词开头)功能的查询。我的文件是这样的:mongodb快速标签查询

{ 
    "_id": "theid", 
    "somefield": "some value", 
    "tags": [ 
     { 
      "name": "abc tag1", 
      "vote": 5 
     }, 
     { 
      "name": "hij tag2", 
      "vote": 22 
     }, 
     { 
      "name": "abc tag3", 
      "vote": 5 
     }, 
     { 
      "name": "hij tag4", 
      "vote": 77 
     } 
    ] 
} 

举例来说,如果我的查询将是与“AB”开头,并有一个“somefield”,即“一些价值”的结果将是“ABC标签1”的标签, “abc tag3”(仅限名称)。 我关心查询的速度远远超过插入和更新的速度。

我认为聚合框架将会是正确的方式,但是对于非常快速的查询,最好的管道和索引是什么?

这些文档不是'标签'文档,它们是代表客户端对象的文档,它们包含更多的数据字段,为了简单起见我省略了每个客户端有几个标签和另一个字段(我更改了它的名称,所以它不会是与标签数组混淆)。我需要获得一组没有一组客户端所有标签的重复内容。

+0

我曾尝试做类似的去年,但数据库更小。随着数据量的增长,我最终不得不使用Solr。 – Martin 2014-09-29 18:43:23

+0

你可以发布你试过的查询和索引吗?你使用聚合框架吗? – jacob 2014-09-29 19:28:15

+0

对不起,代码已经过去了,但它是基于标记字段上的正则表达式。它预先聚合框架,但我不知道这将是最好的方法。根据我的经验,聚合框架喜欢将整个文档读入内存,即使$匹配只能使用索引 – Martin 2014-09-30 08:47:35

回答

0

你的文档结构没有意义 - 我假设tags是一个数组而不是一个对象。尝试像这样的查询

db.tags.find({ "somefield" : "some value", "tags.name" : /^abc/ }) 

索引{ "maintag" : 1, "tags.name" : 1 }。 MongoDB将左锚定正则表达式查询优化为范围查询,这可以使用索引高效地实现(请参阅$regex docs)。

你可以只使用一个聚合管道从这个文档结构标签:

db.tags.aggregate([ 
    { "$match" : { "somefield" : "some value", "tags.name" : /^abc/ } }, 
    { "$unwind" : "$tags" }, 
    { "$match" : { "tags.name" : /^abc/ } }, 
    { "$project" : { "_id" : 0, "tag_name" : "$tags.name" } } 
]) 

指数不仅有助于为第一$比赛,所以相同的索引管道作为查询。

+0

您是对的我的对象有错误,我修正了它。您的查询将返回所有符合条件的文档,我只需要一个无重复的标签列表。否则我将获取所有不必要的数据。 – jacob 2014-09-30 15:26:01

+0

$位置操作符可以输出1个匹配的标签。如果你确实需要返回所有标签,那么你已经不适当地构建你的文档。这些文档应该是主标签非标准化的标签,而不是带有标签的主标签文档。 – wdberkeley 2014-09-30 17:44:55

+0

我想我的问题并不清楚,请参阅我的编辑。它不是一个标签文档,它是一个带有嵌套的士气低落的标签阵列的客户端文档。 – jacob 2014-09-30 18:19:44