我有这样的文档:
...
propA:[0, 2, 6], //Array of unique numbers of length max. ~50
propB:[2, 14, 24, 39],//Array of unique numbers of length max. ~50
propC:[1, 14, 29], //Array of unique numbers of length max. ~50
...
我希望能够以这样的方式查询它们:
- 我可以匹配所有文档与某些属性
- 我可以匹配所有没有特定属性的文档
例如,现在我使用查询:
mongo.db.collection('things').find({
propA:{$all:[...], $nin:[...]},
propB:{$all:[...], $nin:[...]},
propC:{$all:[...], $nin:[...]},
})
但是它真的很慢而且伸缩性很差,因为mongo必须扫描每个文档。
使mongo查询更快的解决方案是:
- 创建索引
- 更改文档架构
问题是我不能.createIndex({propA:1, propB:1, propC: 1})
,因为mongo不接受索引多个数组字段(有很好的理由)。
但是当我使用另一个模式时,比如:
...
props:["a0", "a2", "a6", "b2", "b14", "b24", "b39", "c1", "c14", "c29"]
...
并在{props: 1}
上创建一个索引,查询方式与上面相同,执行如下:
- 第一阶段:IXSCAN,非常快,但它只选择第一个属性(例如:"a0")
- 第二阶段:FETCH,非常慢,必须扫描通过IXSCAN的所有文档
我的问题是:
如何最有效地查询数组文档?
我是OP,我想我找到了最佳的"方法:regex
例如,不存储
propA:[0, 2, 6],
propB:[2, 14, 24, 39],
propC:[1, 14, 29],
存储
props: "a0a2a6b2b14b24b39c1c14c29" //a string, really
创建索引.createIndex({"props": "text"})
例如,要搜索包含a1, b5, b7而不包含a3, b4和c8的文档,您可以查询:
mongo.db.collection('things').find({
props: {
$regex: /.*a1.*^a3.*^b4.*b5.*b7.*c8/
}
})
考虑到它,我不知道如何在几毫秒内查询具有数百万个文档的集合,但好的事情是它是。
只有一个"small"问题:
- 查询高于所有文档的属性。
奇怪的是,如果集合的最大propA是19,而您查询20 mongo确实扫描所有文档而不是使用索引,我想一个简单的修复方法是添加"x999"在系列之间,但仍然很丑。
例如,存储:
props: "a0a2a6a999b2b14b24b39b999c1c14c29c999" //another string
我仍然期待更好的选择,的确,你不能像.createIndex({"location": "2dsphere", "props": "text"})
那样做一个复合指数。