许多(嵌套)字段/属性上的MongoDB索引

时间:2013-10-30 19:25:52

标签: mongodb

在电子商务应用程序中,我有这样的文档:

{ category:'A', ..., price:122,
  attr:{ width:6, height:4, hasLCD:true, lcdType:'some text', ..., a36:null }
}

即。每个产品都有各种简单类型的许多属性。

现在我想通过包含顶级字段和一些属性的动态查询来过滤产品。例如:

find({category:'A', price:{$lt:200}, ...,
     'attr.height':{$lt:6}, 'attr.hasLCD':true, 'attr.lcdType':{$in:[...]}, ...})

我希望这能快速完成。

尝试索引所有可能的'attr。*'变体会给我一个错误(复合键太多)。我也怀疑如果我以这种方式索引它然后省略查询索引中的一个attrs将无法工作。

尝试将“attr”作为一个整体进行索引也无济于事。

在MongoDB下对此进行建模的正确方法是什么?

更新

我尝试了this方法(也提到了here)。即将属性存储为键值对的数组:

attr2: [ {tag:'lcgType', value:'some text'}, ...

并将其编入索引:

ensureIndex({ 'attr2.tag':1, 'attr2.value':1 })

并且像这样查询:

find({attr2:{$all:[
  {$elemMatch:{tag:'bestseller',value:true}},
  {$elemMatch:{tag:'weight',value:{$lte:100}}}
]}})

现在explain()说它正在使用"BtreeCursor attr2.tag_1_attr2.value_1"但仍然是"nscanned" : 31607,并且整个执行时间实际上已经增加(与非索引方案相比)。

这里出了点问题。

子问题

如果我选择一些(少于31个)最常查询的属性并尝试对其进行索引,该怎么办?如果我将所有这些都放在单个复合索引中:

ensureIndex({'attr.a1':1, 'attr.a2':1, ...})

根据docs,此索引不会用于缺少attr.a1属性的查询。

在这种情况下如何定义索引?

1 个答案:

答案 0 :(得分:2)

如果确实必须允许大量过滤器,组合甚至可能排序,MongoDB不适合使用only one index per query。然后索引的数量增长得太快,因为compound keys are somewhat inflexible(应该回答子问题)并且变成了性能损失。

使用像ElasticSearch,SolR等搜索数据库来代替您需要的功能。如果要在MongoDB中保留基本信息,可以在搜索服务器返回的ID上使用$in(通常最好让搜索数据库只复制主数据存储的信息,这样您就可以了不需要双向同步更改,这将是一场噩梦)