MongoDB:多个$ elemMatch

时间:2014-07-29 11:54:48

标签: mongodb pymongo

我的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存在等效代码,则知道如何编写它。

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

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

2 个答案:

答案 0 :(得分:20)

在这种情况下,您可以使用$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

答案 1 :(得分:4)

var fruits = db.fruits.find({
    "vitamins": {
        $all: [{
            $elemMatch: {
                "name": "A1",
                "state": "non_free"
            }
        }, {
            $elemMatch: {
                "name": "B7",
                "state": "free"
            }
        }]
    }
})