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

Posted

技术标签:

【中文标题】在 MongoDB 中查找与对象数组中的多个字段匹配的文档【英文标题】:Find documents matching multiple fields in an object array in MongoDB 【发布时间】:2022-01-18 21:34:22 【问题描述】:

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

文档不具备数组 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 并为它的每个元素执行一个查询,匹配我需要的所有字段,但这似乎效率不高。

【问题讨论】:

我有这个问题,***.com/questions/70368089/…,这个数据 $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") ] 它仍然给我同样的错误结果。 【参考方案1】:

听起来您想将数组中子文档的结构与数组指定的许多可能结构之一进行匹配。我将举例说明如何在 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 = 2id_bus_variation = 3) 或 (id_bus = 3id_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 时已经习惯了这样做,但在这个项目中并没有想到它。谢谢你的回答。 是否有一个简单的单行程序可以返回 "id_bus" : 2, "id_bus_variation" : 2 的所有文档,在这种情况下,是_id 0 和1 的文档?【参考方案2】:

我不知道我是否理解你的问题。

你的收藏可能是这样的


"_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 为“真”时,您才想检索文档

你可以试试

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 在 Document 中时才检索 Document。 例如

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])

你没有任何结果。

如果你想要 Object 中的元素

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

仅当两个值都为“true”时才返回文档

【讨论】:

问题是我事先没有 id_bus 和 id_bus_variation 值,它们位于一个长度不同的数组中。 @Barno 如果我们想要数组中的完全匹配以及基于 id 的比较,那么这个查询将如何被修改? Id 在数组 db.stack.find ( bus: "$elemMatch" : id_bus:1, id_bus_variation : 13 ) 之外

以上是关于在 MongoDB 中查找与对象数组中的多个字段匹配的文档的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB - 查找 - 多个集合 - 结果在一个数组中

mongoDB对嵌套对象数组的聚合查找

mongodb $查找带有投影的数组中的嵌套对象

MongoDB - 基于嵌套数组的字段值更新数组对象中的字段

Mongodb检查数组的子文档中是否存在字段

Mongoose:如何从对象数组中查找多个字段