我得到了以下查询:
db.getCollection('Messages').aggregate(
{
$match :
{
"header.MessageType" : { $in: ["04"] },
}
},
{
$project:
{
_id: '$_id',
header: '$header',
content: '$content',
q0: { $arrayElemAt: [ "$content.Changes", 0 ] },
q1: { $arrayElemAt: [ "$content.Changes", 1 ] },
q2: { $arrayElemAt: [ "$content.Changes", 2 ] },
q3: { $arrayElemAt: [ "$content.Changes", 3 ] },
q4: { $arrayElemAt: [ "$content.Changes", 4 ] },
q5: { $arrayElemAt: [ "$content.Changes", 5 ] },
}
},
{
$match :
{
"q0":"1"
}
},
{
$sort : { "sequenceID" : -1, }
},
{
$limit : 1
}
);
这给了我以下结果:
/* 1 */
{
"_id" : ObjectId("57288ecb53f65928c4ba4995"),
"header" : {
"MessageType" : "04",
...
},
"content" : {
...
},
"q0" : "1",
"q1" : "0",
"q2" : "1",
"q3" : "0",
"q4" : "0",
"q5" : "0"
查询给了我最近的文档(根据sequenceID),它的"q0"肯定等于1(其他qx字段可能是0或1)。我想对q1,q2,…做同样的操作,。。。,q5。换句话说,我想要一个包含6条记录的结果,每条记录代表其"qn"(n=0..5)记录肯定为"0"的最新文档。
是否可以重复以下部分6次(针对$match部分中的不同qx值),然后将它们组合起来?
{
$match :
{
"q0":"1"
}
},
{
$sort : { "sequenceID" : -1, }
},
{
$limit : 1
}
或者有更好的解决方案吗?
---EDIT(添加了一些示例[和简化]数据):
/* 1 */
{
"_id" : ObjectId("57288fa553f65928c4bf4b2b"),
"header" : {
"MessageType" : "04"
},
"content" : {
"Changes" : [
"0",
"1",
"1",
"1",
"1",
"0"
]
},
"sequenceID" : NumberLong(369851),
"messageDate" : 13950214
}
/* 2 */
{
"_id" : ObjectId("57288fa453f65928c4bf4863"),
"header" : {
"MessageType" : "04"
},
"content" : {
"Changes" : [
"0",
"0",
"1",
"0",
"0",
"0"
]
},
"sequenceID" : NumberLong(369139),
"messageDate" : 13950214
}
/* 3 */
{
"_id" : ObjectId("57288fa353f65928c4bf43c2"),
"header" : {
"MessageType" : "04"
},
"content" : {
"Changes" : [
"0",
"1",
"0",
"0",
"0",
"0"
]
},
"sequenceID" : NumberLong(367953),
"messageDate" : 13950214
}
每个文档指示一个或多个(最多6个)修改。修改内容见q0..q5字段。作为输出,我需要的是每个qx字段的最新更改。文档的顺序可以通过"sequenceID"字段来确定。换言之,如果我(逻辑上做一个)或结果中所有文档的q0..q5,它应该是["1","1"、"1"one_answers"1"]。
实际上,aggregate
函数被称为管道,只是因为它将数据从一个聚合运算符管道传输到另一个,而需要多少管道才能获得最终结果取决于您。
e.g.
$match -> $project -> $group -> $sort -> $match -> $sort -> $limit -> $project
您可以多次使用任何运算符。
db.getCollection('Messages').aggregate(
[
{ $match : { "header.MessageType" : { $in: ["04"] }}},
{
$project:
{
_id: '$_id',
"MessageType": '$header.MessageType',
q0: { $arrayElemAt: [ "$content.Changes", 0 ] },
q1: { $arrayElemAt: [ "$content.Changes", 1 ] },
q2: { $arrayElemAt: [ "$content.Changes", 2 ] },
q3: { $arrayElemAt: [ "$content.Changes", 3 ] },
q4: { $arrayElemAt: [ "$content.Changes", 4 ] },
q5: { $arrayElemAt: [ "$content.Changes", 5 ] },
}
},
{$match : { "q0" : "0" } },
{$sort : { "q1" : -1}},
{$match : {"q3" : "1"}}
]
)
现在,最后要添加的是按您所说的添加6个匹配子句,即使您使用的是索引,也会减慢查询速度,如果您的集合很大,则需要一些时间才能从聚合管道中传输所有数据。所以明智地使用这个管道。
执行$match后,未选中的文档将从流程管道中删除。
我的建议是更换
{
$match :
{
"q0":"1"
}
},
带有
{
$group:{
_id:{include fields here},
q0:{$push:"$q0"},
...............,
q5:{$push:"$q5"}
},
}
之后,我们可以对具有完整结果集的数组进行操作。
所以我们可以使用$filter
{ $filter: { input: "q0", as: q0Filtered, cond: {$eq:1} } }
这对你有用吗?
欢迎任何评论!
在一个查询中不能使用多个匹配,如果执行了匹配,则除第一个匹配之外的所有语句都将被忽略。