在电子商务应用程序中,我有这样的文档:
{ 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
属性的查询。
在这种情况下如何定义索引?
答案 0 :(得分:2)
如果确实必须允许大量过滤器,组合甚至可能排序,MongoDB不适合使用only one index per query。然后索引的数量增长得太快,因为compound keys are somewhat inflexible(应该回答子问题)并且变成了性能损失。
使用像ElasticSearch,SolR等搜索数据库来代替您需要的功能。如果要在MongoDB中保留基本信息,可以在搜索服务器返回的ID上使用$in
(通常最好让搜索数据库只复制主数据存储的信息,这样您就可以了不需要双向同步更改,这将是一场噩梦)