48

我已经将此作为对另一个问题的评论提出,并且还在mongodb-user 上发布了一个问题。到目前为止没有任何回应,所以我求助于另一个问题。

文档指出:

如果该字段包含一个数组,则 $in 运算符选择其字段包含一个数组的文档,该数组包含至少一个与指定数组中的值匹配的元素(例如,等)

我在用着:

mongod --version:
db version v2.2.2, pdfile version 4.5
Thu May 30 12:19:12 git version: d1b43b61a5308c4ad0679d34b262c5af9d664267

mongo --version:
MongoDB shell version: 2.0.4

在 MongoDB 外壳中:

db.nested.insert({'level1': {'level2': [['item00', 'item01'], ['item10', 'item11']]}})

以下是应该根据文档工作的查询列表,以及它们产生的结果:

为什么这不起作用?

> db.nested.findOne({'level1.level2.0': 'item00'})
null

为什么我需要 $all?

> db.nested.findOne({'level1.level2.0': {'$all': ['item00']}})
{
    "_id" : ObjectId("51a7a4c0909dfd8872f52ed7"),
    "level1" : {
        "level2" : [
            [
                "item00",
                "item01"
            ],
            [
                "item10",
                "item11"
            ]
        ]
    }
}

以下至少一项应该有效,对吧?

> db.nested.findOne({'level1.level2.0': {'$in': ['item00']}})
null

> db.nested.findOne({'level1.level2': {'$in': ['item00']}})
null

有任何想法吗?如果查询语法不像宣传的那样工作,我们正在考虑放弃 MongoDB。

谢谢!

4

3 回答 3

46

在运行了一些查询之后,我得出的结论是$in 不适用于数组数组

您可以改用$elemMatch它,它会起作用,但令人沮丧的是 MongoDB 的文档没有警告它。

我创建了这个文档:

{
      "_id": "51cb12857124a215940cf2d4",
      "level1": [
        [
          "item00",
          "item01"
        ],
        [
          "item10",
          "item11"
        ]
      ],
      "items": [
        "item20",
        "item21"
      ]
}

请注意,“items”字段是一个字符串数组,此查询完美运行:

db.nested.findOne({"items":{"$in":["item20"]} })

现在,“level1.0”也是一个字符串数组,唯一的区别是它在另一个数组中。此查询应该有效,但不是:

db.nested.findOne({"level1.0":{"$in":["item00"]} })

获得结果的唯一方法是使用 $elemMatch:

db.nested.findOne({"level1":{"$elemMatch":{"$in":['item00']}} })

所以$elemMatch解决了这个问题,但真正的解决方案是将 MongoDB 的文档更新为$in不适用于数组数组的状态。也许您应该向 10gen 提交请求。

于 2013-06-26T17:54:51.777 回答
10

使用嵌套elemMatch在数组中搜索嵌套级别。

MongoDB 中查询数组数组的详细信息

于 2013-06-26T23:50:22.133 回答
6

简短的回答:$in 用于单值字段,$all 用于数组。

首先,db.nested.findOne({'level1.level2.0': 'item00'})它不起作用,因为 level1.level2.0 包含一个数组,而您正试图将它与单个值进行比较。

现在,db.nested.findOne({'level1.level2.0': {'$in': ['item00']}})由于类似的原因,它也不起作用。$in 用于将具有单个值(您有一个数组)的字段与数组中的多个值(在查询中指定)进行比较。$in 是说:给我具有此字段的文档,该字段的值包含在此数组中。

$all 正在工作,因为它在说:给我具有该字段的多个值的文档,并且该数组的所有值(在查询中)都包含在该字段中。(已编辑)

可能很难获得,但请查看文档中的每个内容:

$all 选择字段包含数组并包含数组中所有元素 (e.g. <value>, <value1>, etc.的文档。

$in 选择字段值等于指定数组中任意值的文档( e.g. <value1>, <value2>, etc.)

希望能帮助到你

于 2013-06-25T20:01:44.820 回答