4

这是我的文件:

{ "_id" : ObjectId("5259b73b4949e0b22608960d"), "array" : [  "a",  "b" ] }

要在该字段中查找某些值,array我使用以下查询:

db.collection.find({roles: 'a'})

但是我遇到了这个问题,当该array字段看起来像这样时:

{ "array": { '0': 'a', '1' : 'b' } }

如何使用这种数组(实际上是所有字段都是数组索引的子文档)执行与以前相同的查询?所以我需要找到一个文档,其中任何子文档的字段都等于某个值。

不幸的是,我无法更改此字段,因为它是由第 3 方 API 生成的。

4

2 回答 2

2

我认为没有比使用operator更好的选择$where,它允许您通过指定自定义 JavaScript 函数来过滤集合。

请注意,对于大型集合,这可能会导致性能问题,因为$where条件无法利用索引。

好的,回到问题:在{ "array": { '0': 'a', '1' : 'b' } }字面上,array从技术上讲,它不是一个数组,而是一个具有 、 和 属性'0''1'对象'2'

假设所有array对象都将具有从 开始的连续属性列表'0',您可以迭代直到找到匹配项或iarray[i]is的数字undefined(表示连续属性序列的结束)。

实现这一点的 JavaScript 函数是:

function () {
    for(var i = 0; this.array[i] !== undefined; i++) {
        if(this.array[i] === 'b') {
            return true;
        }
    } 

    return false; 
}

为了轻松地将其粘贴到 Mongo shell 中,这里是单行版本:

function () {for(var i=0; this.array[i]!==undefined; i++) {if(this.array[i]==='b') {return true; } } return false; }

请注意有关上述脚本的两件事:

  • this.array如果属性的名称不同于"array"
  • 'b'是要在"array"中搜索的值。将其更改为您要搜索的任何内容。

因此,使用上面的脚本,这就是您可以在 Mongo shell 中编写的内容:

db.arraycollection.find({$where: function() {for(var i=0; this.array[i]!==undefined; i++) {if(this.array[i]==='b') {return true; } } return false; }});

为了简化一点,因为这是 的唯一条件find(),我们可以完全省略$where,只留下 js 函数作为参数:

db.arraycollection.find(function() {for(var i=0; this.array[i]!==undefined; i++) {if(this.array[i]==='b') {return true; } } return false; });

PS:很抱歉上面的长行让你滚动,但我认为单行更方便粘贴在 Mongo shell 中。

于 2013-10-16T07:21:09.820 回答
0

您可以使用$elemMatch找到数组的子文档:

db.collection.find( { "_id" : ObjectId("5259b73b4949e0b22608960d") },
             { array: { $elemMatch: { 0: '1'} } )

这将从您的集合中找到具有特定对象 id 的“数组”,以及匹配 {0: '1'} 对象的数组对象。

于 2013-10-16T05:50:47.313 回答