MongoDb,查询最后一个,然后分组

时间:2015-08-21 06:37:24

标签: mongodb mongodb-query aggregation-framework

我在处理MongoDb时遇到了麻烦。

我需要:

  • 获取所有最后的条目
  • 关于一个领域
  • like:SELECT MAX(id),foreignKey FROM t_table GROUP BY foreignKey

我知道我们可以使用$ last和mongodb,但我根本不知道如何继续。

我试过了:

db.collection.aggregate(
   [
     {
       $group:
         {
           _id: "$zone._id",
           lastRegistered: { $last: "$_id" }
         }
     }
   ]
)

但它确实似乎给了我需要的东西

使用示例编辑

根据这三个:

  { _id: 55d5a01f9f58d2cc0eb79f5d,
    controlDate: Thu Aug 20 2015 11:38:40 GMT+0200 (Paris, Madrid (heure d’été)),
    zone:
     { _id: 55cb5bb42d191d2022c5c266,
       zoneName: 'Syphon 1',
     },
    actif: true 
    },



  { _id: 55d59f129f58d2cc0eb79f5c,
    controlDate: Fri Aug 21 2015 07:34:12 GMT+0200 (Paris, Madrid (heure d’été)),
    zone:
     { _id: 55cb5bb42d191d2022c5c266,
       zoneName: 'Syphon 1',
     },
    actif: true 
    }



  { _id: 55d5a01f9f58d2cc0eb79f5e,
        controlDate: Fri Aug 20 2015 08:38:40 GMT+0200 (Paris, Madrid (heure d’été)),
        zone:
         { _id: 55cb5bb42d191d2022c5c278,
           zoneName: 'Other zone',
         },
        actif: true 
        },

我需要得到:

  { _id: 55d59f129f58d2cc0eb79f5c,
    controlDate: Fri Aug 21 2015 07:34:12 GMT+0200 (Paris, Madrid (heure d’été)),
    zone:
     { _id: 55cb5bb42d191d2022c5c266,
       zoneName: 'Syphon 1',
     },
    actif: true 
    }



  { _id: 55d5a01f9f58d2cc0eb79f5e,
        controlDate: Fri Aug 20 2015 08:38:40 GMT+0200 (Paris, Madrid (heure d’été)),
        zone:
         { _id: 55cb5bb42d191d2022c5c278,
           zoneName: 'Other zone',
         },
        actif: true 
        },

这意味着:我需要获取按区域_id分组的此集合的最后一个(按ID或日期,不要介意)。 (2行,因为我有1个区域的2个数据集(我只需要最后一个)而我需要最后一个区域(只有1行所以......)。

你知道我的意思吗?

2 个答案:

答案 0 :(得分:5)

$last为您提供分组处理的最后一个文档的值。除非对文档进行排序,否则无法预测文档的处理顺序。所以你没有得到你期望的结果。

尝试在$ group阶段之前添加$ sort阶段,以按升序日期顺序获取文档:

db.collection.aggregate(
   [
     { $sort: {
           "control_date":1
       }
     },
     {
       $group:
         {
           _id: "$zone._id",
           lastRegistered: { $last: "$_id" },
           zoneName:"$zone.zoneName",
           control_id:"$_id",
           actif:"$actif",
         }
     }
   ]
)

答案 1 :(得分:4)

您始终可以使用$$ROOT在分组边界上返回整个文档:

db.collection.aggregate([
    { "$group": { 
        "_id": "$zone._id",
        "doc": { "$last": "$$ROOT" }
    }}
 ])

或者使用直接排序控制而不是自然顺序:

db.collection.aggregate([
    { "$sort": { "_id": 1 } },
    { "$group": { 
        "_id": "$zone._id",
        "doc": { "$last": "$$ROOT" }
    }}
  ])

但请注意,$group管道不保证保留的文档顺序,因此如果您需要,那么再次$sort

db.collection.aggregate([
    { "$sort": { "_id": 1 } },
    { "$group": { 
        "_id": "$zone._id",
        "doc": { "$last": "$$ROOT" }
    }},
    { "$sort": { "doc._id": 1 } }
 ])

在所有情况下,对$$ROOT的更改只是为文档中的每个字段明确声明$last。相比之下,$max运算符仅适用于指定的字段,因此当您希望分组边界的文档为$last时,这通常对您没用。

考虑那里的“最后”示例,并从示例中删除相应的数据,然后我得到:

{
    "_id" : "55cb5bb42d191d2022c5c266",
    "doc" : {
            "_id" : "55d5a01f9f58d2cc0eb79f5d",
            "zone" : {
                    "_id" : "55cb5bb42d191d2022c5c266",
                    "zoneName" : "Syphon 1"
            },
            "actif" : true
    }
},
{
    "_id" : "55cb5bb42d191d2022c5c278",
    "doc" : {
            "_id" : "55d5a01f9f58d2cc0eb79f5e",
            "zone" : {
                    "_id" : "55cb5bb42d191d2022c5c278",
                    "zoneName" : "Other zone"
            },
            "actif" : true
    }
}

改变输入是:

{
    "_id" : "55d5a01f9f58d2cc0eb79f5d",
    "zone" : {
            "_id" : "55cb5bb42d191d2022c5c266",
            "zoneName" : "Syphon 1"
    },
    "actif" : true
},
{
    "_id" : "55d59f129f58d2cc0eb79f5c",
    "zone" : {
            "_id" : "55cb5bb42d191d2022c5c266",
            "zoneName" : "Syphon 1"
    },
    "actif" : true
},
{
    "_id" : "55d5a01f9f58d2cc0eb79f5e",
    "zone" : {
            "_id" : "55cb5bb42d191d2022c5c278",
            "zoneName" : "Other zone"
    },
    "actif" : true
}

如果十六进制字符串值是词法,就像ObjectId的内部排序一样,那么不要打扰正确的ObjectId值。

这是集合中每个提供的zone._id值的“最后”文档,按原始文档_id值排序。