我在 MongoDB 中有以下类型的数据(从我的真实案例中简化了一点):
{
"name":"some name",
"attrs":[
{"n":"subject","v":"Some subject"},
{"n":"description","v":"Some great description"},
{"n":"comments","v":"Comments are here!"},
]
}
Run Code Online (Sandbox Code Playgroud)
attrs 数组是动态属性的容器,即我事先不知道放置了什么样的属性。n 代表名称,v 代表价值。
MongoDB In Action 一书将其描述为在属性完全可预测的情况下具有动态属性的解决方案。它还描述了您可以像这样对其进行索引:
db.mycollection.ensureIndex({"attrs.n":1, "attrs.v":1})
Run Code Online (Sandbox Code Playgroud)
然后可以像这样完成查询:
db.mycollection.find({attrs: {$elemMatch: {n: "subject", v: "Some subject"}}})
Run Code Online (Sandbox Code Playgroud)
当我测试这个时,我的性能很差。我用 mycollection 测试了 200 万个文档并且没有索引似乎表现更好。
那么,问题来了,有没有办法索引这种动态属性设置,以便索引提供良好的性能?就我而言,仅拥有“主题”和“描述”之类的键并将它们全部编入索引是不可行的......
我也在mongodb-user mailing list上问了同样的问题(以稍微扩展的形式),我在那里得到了答案。从那里阅读以获取更多详细信息。简短的回答是,问题中使用的策略应该可以正常工作,但是有一个问题使其效率非常低。希望这个问题能很快得到解决。
对于我的情况,我只需要查询元组 {n,v} 的精确匹配,这样我就可以创建一个多键索引:
db.mycollection.ensureIndex({"attrs":1})
Run Code Online (Sandbox Code Playgroud)
并让他们这样查询:
db.mycollection.find({"attrs": {n: "subject", v: "Some subject"}})
Run Code Online (Sandbox Code Playgroud)
这很好用并且非常有效地使用索引。