I have a document like this..
{
"_id" : ObjectId("59b0ea9b3a91af574a3e0464"),
"machineID" : "b83c",
"sensorState" : [
{
"data" : "377",
"sensor" : "solar",
"time" : ISODate("2017-09-20T19:42:58.766Z")
},
{
"data" : "35",
"sensor" : "photosynthetic",
"time" : ISODate("2017-09-20T19:42:58.782Z")
},
{
"data" : "370",
"sensor" : "solar",
"time" : ISODate("2017-09-20T19:43:29.089Z")
},
{
"data" : "400",
"sensor" : "solar",
"time" : ISODate("2017-09-20T19:44:29.089Z")
},
{
"data" : "35",
"sensor" : "photosynthetic",
"time" : ISODate("2017-09-20T19:43:29.110Z")
}
]
}
I want to retrieve only those sub documents in the sensorState
array which match sensor=solar
. So, I tried to do like this:
db.getCollection('sensorDB').find({ },
{ "sensorState" : { $elemMatch: {data : "35" } } })
But it shows only one result:
{
"_id" : ObjectId("59b0ea9b3a91af574a3e0464"),
"sensorState" : [
{
"data" : "35",
"sensor" : "photosynthetic",
"time" : ISODate("2017-09-20T19:42:58.782Z")
}
]
}
However, I want to find all sub documents in the sensorState
array which match sensor=solar
. It looks like $elemMatch
just can select one result.
答案 0 :(得分:1)
您正尝试使用elemMatch进行投影但是根据the docs
$elemMatch
运算符将查询结果中字段的内容限制为仅包含与$elemMatch
条件匹配的第一个元素。
因此,您看到的行为是elemMatch-in-a-projection的预期行为。
您可以在汇总管道中使用$project
和$filter
来获取最终结果。
鉴于您的OP中包含的示例文档,请执行以下命令...
db.getCollection('elemMatch').aggregate([
// projects on the sensorState sub documents and filters the output to only return sub
// documents having data=35
{$project: {
sensorState: {
$filter: {
input: "$sensorState",
as: "sensorState",
cond: { $eq: [ "$$sensorState.data", '35' ] }
}
}
}
}
])
...将返回:
{
"_id" : ObjectId("59b0ea9b3a91af574a3e0464"),
"sensorState" : [
{
"data" : "35",
"sensor" : "photosynthetic",
"time" : ISODate("2017-09-20T19:42:58.782Z")
},
{
"data" : "35",
"sensor" : "photosynthetic",
"time" : ISODate("2017-09-20T19:43:29.110Z")
}
]
}
您的问题显示了data=35
上的尝试匹配,但它也说明了:
我想找到所有sensorState.sensor = solar
所以,这是带有该条件的上述命令:
db.getCollection('elemMatch').aggregate([
// projects on the sensorState sub documents and filters the output to only return sub
// documents having sensor=solar
{$project: {
sensorState: {
$filter: {
input: "$sensorState",
as: "sensorState",
cond: { $eq: [ "$$sensorState.sensor", 'solar' ] }
}
}
}
}
])
返回:
{
"_id" : ObjectId("59b0ea9b3a91af574a3e0464"),
"sensorState" : [
{
"data" : "377",
"sensor" : "solar",
"time" : ISODate("2017-09-20T19:42:58.766Z")
},
{
"data" : "370",
"sensor" : "solar",
"time" : ISODate("2017-09-20T19:43:29.089Z")
},
{
"data" : "400",
"sensor" : "solar",
"time" : ISODate("2017-09-20T19:44:29.089Z")
}
]
}
答案 1 :(得分:1)
我自己找到了答案。使用聚合 答案是这样的
db.getCollection('sensorDB').aggregate(
{$match: {machineID:"b83c"}},
{$unwind:"$sensorState"},
{$match: {"sensorState.sensor":"solar"}}
)