MongoDB elemMatch在预期中不起作用



我正在尝试获取符合我条件的子文档。

我的MongoDB查询是这样的:

db.SCSIssue.find(
 { _id: ObjectId("5439a2992ea8cc0f70feef2d") }, 
 { Statuses: { $elemMatch: { StatusID: { $gte : NumberLong(521055087020736513) } } } }
)

我的架构是这样的:

{
    ....
    "_id": ObjectId("5439a2992ea8cc0f70feef2d"),
    ....
    "Statuses": [{
        ....
        "StatusID": NumberLong(525623822633172993),
    },{
        ....
        "StatusID": NumberLong(521055087020736513),
    },{
        ....
        "StatusID": NumberLong(521060802959532033),
    }]
    ....
},
{
    ....
    "_id": ObjectId("543c04662ea8cd11ec4dda5f"),
    ....
    "Statuses": [{
        ....
        "StatusID": NumberLong(535623822633172993),
    },{
        ....
        "StatusID": NumberLong(541055087020736513),
    },{
        ....
        "StatusID": NumberLong(551060802959532033),
    }]
    ....
},
....

查询结果:

{
    "_id" : ObjectId("5439a2992ea8cc0f70feef2d"),
    "Statuses" : [{
        ....
        "StatusID": NumberLong(525623822633172993),
        ....
    }]
}

预期成果:

{
    "_id" : ObjectId("5439a2992ea8cc0f70feef2d"),
    "Statuses" : [{
        ....
        "StatusID": NumberLong(521055087020736513),
    },{
        ....
        "StatusID": NumberLong(521060802959532033),
    }]
}

简而言之,我想在数组(状态)中获取大于或等于我的条件的子文档,同时_id等于我的条件。我已经读过很多关于这个问题的答案。他们都喜欢我的问题,但在我的情况下,它不是预期的。

我错过了什么?谢谢。

$elemMatch的行为没有错。它按预期工作。文档还说:

但是,$elemMatch投影仅返回第一个匹配项 元素。

根据经验,每当使用 $elemMatch 投影array时,最多只会投影一个元素。如果数组中的任何元素都不匹配,则根本不会投影该字段。

因此,您得到的结果是正确的,只有数组中与$elemMatch中的条件匹配的第一项才会被projected

{
    "_id" : ObjectId("5439a2992ea8cc0f70feef2d"),
    "Statuses" : [{
        ....
        "StatusID": NumberLong(525623822633172993),
        ....
    }]
}

您可以尝试更改 statuses 数组中文档的顺序,如果该文档出现在数组中其他匹配文档之前,则可能会获得不同的匹配文档。

参考: $elemMatch

根据您的要求,如果您希望结果中包含所有匹配的数组元素,则需要执行聚合操作。

  • Match具有所需_id的文件和这些文件其中包含我们正在搜索的状态子文档。
  • unwind状态数组。
  • 再次match个别展开的文件。
  • 最后按_id group匹配的文档。

守则:

db.collection.aggregate([
{$match:{ "_id": ObjectId("5439a2992ea8cc0f70feef2d"),
          "Statuses.StatusID":{$gte : NumberLong(525623822633172993)}}},
{$unwind:"$Statuses"},
{$match:{"Statuses.StatusID":{$gte : NumberLong(525623822633172993)}}},
{$group:{"_id":"$_id",statuses:{$push:"$Statuses"}}}
])

这将为您提供数组中所有匹配的子文档。

仅供参考Find 方法有 2 个参数,第一个是要发送到数据库的查询,第二个是投影。当您进行搜索时,您正在发送此...find({query},{projection})

db.SCSIssue.find(
{ _id: ObjectId("5439a2992ea8cc0f70feef2d") }, 
{ Statuses: { $elemMatch: { StatusID: { $gte : NumberLong(521055087020736513)}}}})

您可能想要做的是在 find 方法的查询部分执行所有操作。

db.SCSIssue.find(
{ _id: ObjectId("5439a2992ea8cc0f70feef2d"), 
   Statuses: { $elemMatch: { StatusID: { $gte : NumberLong(521055087020736513)}},
   xxxxx <- second param for the projection part
)

最新更新