简体   繁体   English

索引MongoDB数组位置查询

[英]Indexing MongoDB array position queries

I'd like to build an index that supports queries against specific array element positions. 我想建立一个索引,以支持对特定数组元素位置的查询。

Given several million documents with arrays of values: 给定数百万个具有值数组的文档:

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

I'd like to search for documents with true in position 2. 我想搜索位置2为true文档。

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

If I create a multikey index: 如果我创建一个多键索引:

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

The index supports queries of the form { "array": true } (searching all array elements) but not { "array.2": true } (searching a specific array element). 该索引支持以下形式的查询: { "array": true } (搜索所有数组元素),但不支持{ "array.2": true } (搜索特定数组元素)。

The documentation says "MongoDB creates an index key for each element in the array", so I was expecting that if I created an index on the array field, it would be used for queries on array.0 , array.1 , array.2 , etc. Is there a trick to getting this to work? 文档说“ MongoDB为数组中的每个元素创建一个索引键”,因此我期望如果我在array字段上创建索引,则该索引将用于对array.0array.1array.2查询。 ,等等。有一个技巧可以使它正常工作吗?

MongoDB's multikey index only indexes the values of the array, and not the position of the said value in the array. MongoDB的多键索引仅索引数组的值,而不索引所述值在数组中的位置。

Having said that, there is one possible workaround to do what you require. 话虽如此,有一种可能的解决方法来满足您的要求。

Instead of only storing the value of the array, you would need to store a "key" showing the position of the element. 您不仅需要存储数组的值,还需要存储一个显示元素位置的“键”。 Using your example: 使用您的示例:

> 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}
  ]
}

Note that in the example above, I'm using sub-documents with the field k to denote the "array position", and the field v to store the "array element". 请注意,在上面的示例中,我使用的子文档中的字段k表示“数组位置”,字段v用来存储“数组元素”。

You can then create an index that indexes both fields: 然后,您可以创建索引两个字段的索引:

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

And the query should use the $elemMatch operator to ensure that the whole sub-document matches. 该查询应使用$ elemMatch运算符来确保整个子文档匹配。 Let's say you're searching for the k of 2 and the v of true : 假设您要搜索2的ktruev

> 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}
  ]
}

One drawback of this approach is you need to do your own housekeeping regarding the k field. 这种方法的一个缺点是您需要对k字段进行自己的内务处理。 Inserting into the array are a bit more complex since you have to know the highest value of k before doing $push , if you want to treat k like an array index. 插入到数组中会更加复杂,因为如果您想将k视为数组索引,则必须在执行$push之前知道k最大值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM