我正在尝试获取符合我条件的子文档。
我的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
)