将多个match()结果组合在mongodb聚合框架中

时间:2016-05-09 08:22:22

标签: mongodb aggregation-framework

我收到了以下问题:

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
}

或者有更好的解决方案吗?

---编辑(添加了一些样本[和简化]数据):

/* 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& #34;" 1"" 1"" 1"。]

3 个答案:

答案 0 :(得分:2)

实际上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匹配子句即使你使用索引也会减慢你的查询速度,如果你的集合很大,它需要一些时间来管理汇总的所有数据管道。所以明智地使用这个管道。

答案 1 :(得分:1)

执行$ match后 - 从流程管道中删除未选择的文档。

我建议的是替换

{
    $group:{
        _id:{include fields here},
        q0:{$push:"$q0"},
        ...............,
        q5:{$push:"$q5"}
 },

}

{ $filter: { input: "q0", as: q0Filtered, cond: {$eq:1} } }

之后我们可以对具有完整结果集的数组进行操作。

所以我们可以使用$filter

<?php declare(strict_types=1);

// All other code here
// ...

这对你有用吗?

欢迎任何评论!

答案 2 :(得分:1)

您不能在查询中使用多个匹配项,如果执行该匹配项,则会忽略除第一次匹配之外的所有语句。