在MongoDB中索引多个数组

siotufzp  于 2022-12-03  发布在  Go
关注(0)|答案(1)|浏览(135)

我的文档如下所示:

...
    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的所有文档

所以我的问题是:
如何最有效地查询具有数组的文档?

k3fezbri

k3fezbri1#

我是OP,我想我找到了“最优”的做法:正则表达式
例如,与存储

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/
    }
})

想想看,我不知道如何在几毫秒内查询一个拥有数百万文档的集合,但好的一面是它确实是。
只有一个“小”问题:

  • 查询高于所有文档的属性。

奇怪的是,如果集合的最大propA是19,而您查询了20个mongo确实扫描了所有文档,而不是使用索引,我猜一个简单的修复方法是在序列之间添加“x999”,但仍然很难看。
例如,您可以储存:

props: "a0a2a6a999b2b14b24b39b999c1c14c29c999" //another string

我仍然期待着更好的替代方案,确实,你不能做出像.createIndex({"location": "2dsphere", "props": "text"})这样的复合指数。

相关问题