在MongoDB中查找匹配对象数组中多个字段的文档

12

假设我有一个对象数组(我们称之为A),我需要一个查询来查找MongoDB中的集合,以查找与数组A中对象1的某个属性匹配的所有文档,并将另一个字段匹配到同一对象中的另一个属性。

这些文档并没有数组A中对象具有的所有属性。

为了使事情清楚...

数组A可能看起来像这样...

[{
    id_bus:1,
    id_bus_variation:13,
    ....
},{
    id_bus:2,
    id_bus_variation:184,
    ....
},{
    id_bus:3,
    id_bus_variation:13,
    ....
}]

我的数据库中的文档包括这两个属性,我需要同时匹配这两个属性。例如,我需要在我的数据库中查找具有id_bus == 1id_bus_variation == 13的文档,以及具有id_bus == 2id_bus_variation == 184的文档,但不包括id_bus == 4id_bus_variation == 13的文档。

我真的不知道如何使用单个查询来做到这一点,唯一的解决办法是遍历数组A并为每个元素执行一个查询,匹配所需的所有字段,但这似乎不够高效。


我有这个问题,https://stackoverflow.com/questions/70368089/mongodb-query-only-the-properties-inside-the-object-of-array,使用以下数据 $and: [ {"opening_hours.time": {$elemMatch: { "from": {$lte: ISODate("2001-01-01 03:00:00.000")}}}}, {"opening_hours.time": {$elemMatch: { "to": {$gte: ISODate("2001-01-01 03:00:00.000")}}}} ],但它仍然给我相同的错误结果。 - Aljohn Yamaro
2个回答

12

看起来您想匹配数组中子文档的结构,以匹配由数组指定的多个可能的结构之一。我将在mongo shell中给出一个示例:

> db.test.insert({ 
    "_id" : 0, 
    bus : [
        { "id_bus" : 1, "id_bus_variation" : 1 },
        { "id_bus" : 2, "id_bus_variation" : 2 },
        { "id_bus" : 3, "id_bus_variation" : 3 }
    ]
})
> db.test.insert({ 
    "_id" : 1, 
    bus : [
        { "id_bus" : 1, "id_bus_variation" : 3 },
        { "id_bus" : 2, "id_bus_variation" : 2 },
        { "id_bus" : 3, "id_bus_variation" : 1 }
    ]
})
> db.test.insert({ 
    "_id" : 2, 
    bus : [
        { "id_bus" : 1, "id_bus_variation" : 1 },
        { "id_bus" : 2, "id_bus_variation" : 3 },
        { "id_bus" : 3, "id_bus_variation" : 2 }
    ]
})

如果我们想要返回所有文档,其中 (id_bus = 2 并且 id_bus_variation = 3) 或者 (id_bus = 3 并且 id_bus_variation = 3),如同一个数组中指定的那样。

> var match = [{ "id_bus" : 2, "id_bus_variation" : 3 }, { "id_bus" : 3, "id_bus_variation" : 3 }];

我们可以通过程序构建查询:

> var query = { "$or" : [] }
> for (var i = 0; i < match.length; i++) {
    query["$or"].push({ "bus" : { "$elemMatch" : match[i] } });
}
> db.test.find(query, { "_id" : 1 }) // just get _id's for easy reading
{ "_id" : 0 }
{ "_id" : 2 }

我们得到了预期的结果。


没错,就是这样。很奇怪(也很愚蠢),我在使用PHP + mysql时习惯于这样做,但在这个项目中没有想到。感谢您的回答。 - martskins
有没有一个简单的一行代码可以返回所有符合条件{ "id_bus" : 2, "id_bus_variation" : 2 }的文档,即在这种情况下,_id为0和1的文档? - Rafael Santos

7
我不知道我是否理解了你的问题。
你的收集可以像这样:
{
"_id" : ObjectId("53de54c1560b7815e123792f"),
"bus" : [ 
    {
        "id_bus" : 1,
        "id_bus_variation" : 13
    }, 
    {
        "id_bus" : 2,
        "id_bus_variation" : 184
    }, 
    {
        "id_bus" : 3,
        "id_bus_variation" : 13
    }
]

如果您只想检索当id_busid_bus_variation都为"true"时的文档,可以尝试以下方法:

}

db.stack.find({$and:[{ "bus.id_bus" : 1,"bus.id_bus_variation" : 13},{"bus.id_bus" : 2,"bus.id_bus_variation" : 184}]})

只有在文档中存在 bus.id_busbus.id_bus_variation 时,才能检索该文档。

例如:

db.stack.find({$and:[{ "bus.id_bus" : 1,"bus.id_bus_variation" : 13},{"bus.id_bus" : 2,"bus.id_bus_variation" : 184},{"bus.id_bus":4}]})

没有任何结果。

如果你想精确获取对象内的元素

db.stack.find ( { bus: { "$elemMatch" : { id_bus:1, id_bus_variation : 13} } }  )

只有当两个值都为“true”时,文档才会返回。


问题是我事先没有id_bus和id_bus_variation的值,它们在一个长度会变化的数组中。 - martskins
@Barno 如果我们想要在数组中进行精确匹配,并基于id进行比较,那么这个查询语句应该如何修改?其中id是在数组之外的。db.stack.find({bus: {"$elemMatch": {id_bus: 1, id_bus_variation: 13}}}) - Tejas Ratunawar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接