索引 MongoDB 数组位置查询

Indexing MongoDB array position queries

我想建立一个支持查询特定数组元素位置的索引。

给定数百万个包含值数组的文档:

db.foo.insert({ array: [true, false, null, true] })
db.foo.insert({ array: [false, null, true, true] })

我想搜索第 2 位带有 true 的文档。

db.foo.find({ "array.2": true })

如果我创建一个多键索引:

db.foo.createIndex({ array: 1 })

索引支持 { "array": true } 形式的查询(搜索所有数组元素),但不支持 { "array.2": true } 形式的查询(搜索特定数组元素)。

documentation 表示 "MongoDB creates an index key for each element in the array",所以我希望如果我在 array 字段上创建索引,它将用于 array.0 上的查询, array.1array.2 等。有什么技巧可以让它发挥作用吗?

MongoDB的多键索引只索引数组的值,而不索引所述值在数组中的位置。

话虽如此,有一种可能的解决方法可以满足您的要求。

您需要存储显示元素位置的 "key" 而不是仅存储数组的值。使用您的示例:

> db.test.find()
{
  "_id": 0,
  "a": [
    {"k": 0, "v": true},
    {"k": 1, "v": false},
    {"k": 2, "v": null},
    {"k": 3, "v": true}
  ]
}
{
  "_id": 1,
  "a": [
    {"k": 0, "v": false},
    {"k": 1, "v": null},
    {"k": 2, "v": true},
    {"k": 3, "v": true}
  ]
}

请注意,在上面的示例中,我使用 sub-documents 和字段 k 表示 "array position",字段 v 存储 "array element".

然后您可以创建索引这两个字段的索引:

db.test.createIndex({'a.k':1, 'a.v':1})

并且查询应该使用$elemMatch operator来确保整个sub-document匹配。假设您正在搜索 k of 2 和 v of true:

> db.test.find({a: {$elemMatch: {k:2, v:true}}})
{
  "_id": 1,
  "a": [
    {"k": 0, "v": false},
    {"k": 1, "v": null},
    {"k": 2, "v": true},
    {"k": 3, "v": true}
  ]
}

这种方法的一个缺点是您需要自己处理 k 字段。插入数组有点复杂,因为如果您想将 k 视为数组索引,则在执行 $push 之前必须知道 k 的最大值。