【问题标题】:MongoDB: multiple $elemMatchMongoDB:多个 $elemMatch
【发布时间】:2014-09-20 18:56:13
【问题描述】:

我的 MongoDB 文档结构如下:

{_id: ObjectId("53d760721423030c7e14266f"),
fruit: 'apple',
vitamins: [
    {
     _id: 1,
     name: 'B7',
     usefulness: 'useful',
     state: 'free',
    }
    {
     _id: 2,
     name: 'A1',
     usefulness: 'useful',
     state: 'free',
    }
    {
     _id: 3,
     name: 'A1',
     usefulness: 'useful',
     state: 'non_free',
    }
  ]
}
{_id: ObjectId("53d760721423030c7e142670"),
fruit: 'grape',
vitamins: [
    {
     _id: 4,
     name: 'B6',
     usefulness: 'useful',
     state: 'free',
    }
    {
     _id: 5,
     name: 'A1',
     usefulness: 'useful',
     state: 'non_free',
    }
    {
     _id: 6,
     name: 'Q5',
     usefulness: 'non_useful',
     state: 'non_free',
    }
  ]
}

我想查询并获取同时具有{name: 'A1', state: 'non_free'}{name: 'B7', state: 'free'} 的所有水果。 在最坏的情况下,如果无法获取这些条目并且如果存在 pymongo 的等效代码,我希望至少计算这些条目,以便知道如何编写它。

对于给定的示例,我只想检索苹果(第一个)文档。

如果我使用$elemMatch,它仅适用于一种情况,但不适用于两种情况。例如。如果我查询find({'vitamins': {'$elemMatch': {'name': 'A1', 'state': 'non_free'}, '$elemMatch': {'name': 'B7', 'state': 'free'}}}),它将检索所有带有{'name': 'B7', 'state': 'free'} 的水果。

【问题讨论】:

    标签: mongodb pymongo


    【解决方案1】:
    var fruits = db.fruits.find({
        "vitamins": {
            $all: [{
                $elemMatch: {
                    "name": "A1",
                    "state": "non_free"
                }
            }, {
                $elemMatch: {
                    "name": "B7",
                    "state": "free"
                }
            }]
        }
    })
    

    【讨论】:

    • 请解释你的答案
    • 查询查找满足以下条件的文档 1) 名称:B7 和状态:free 的精确子文档匹配 2) 名称:A1 和状态:non_free 的精确子文档匹配,并且数组应该满足我使用 $all 运算符的两个条件
    • 根据stackoverflow,你应该解释答案
    • 注:“$all 等价于指定值的 $and 操作”来自$all operator docs
    【解决方案2】:

    在这种情况下,您可以使用$and-operator

    试试这个查询:

    find({
        $and: [
             {'vitamins': {'$elemMatch': {'name': 'A1', 'state': 'non_free'} } },
             {'vitamins': {'$elemMatch': {'name': 'B7', 'state': 'free'} } }
        ]
    });
    

    解释为什么您只收到匹配第二个条件的结果:您传递给 MongoDB 的每个 {} 中的对象是键/值对。每个对象的每个键只能存在一次。当您尝试将值分配给同一个键两次时,第二次分配将覆盖第一次。在您的情况下,您为同一对象中的键 $elemMatch 分配了两个不同的值,因此第一个被忽略了。实际到达MongoDB的查询只是find({'vitamins': {'$elemMatch': {'name': 'B7', 'state': 'free'}}})

    每当您需要将同一个运算符两次应用于同一个键时,您需要使用$or$and

    【讨论】:

    • 但我需要水果来同时拥有两种维生素而不是其中任何一种
    • @gevra 我的错,在这种情况下使用$and 而不是$or。更新了答案。
    • 使用$and 代替$or
    • 是否可以为未知数量的 $elemMatch 动态执行类似的操作?
    • @chillinpuma 您可以在应用程序上动态构建传递给$and 的数组。
    猜你喜欢
    • 2023-03-24
    • 2015-05-15
    • 2013-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多