MongoDb, query the last, and group by

后端 未结 2 1281
执笔经年
执笔经年 2021-01-15 14:07

I m actually having trouble when dealing with MongoDb.

I need to :

  • get all of the last entries
  • concerning a field
  • like : SELECT MAX(i
相关标签:
2条回答
  • 2021-01-15 14:40

    You can always use $$ROOT to return the whole document on the grouping boundary:

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

    Or with direct sort control rather than the natural order:

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

    But note that the $group pipeline does not guarantee a retained document order, so if you need that then you $sort again:

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

    In all cases the alterate to $$ROOT is simply to declare $last explicitly for each field you want from the document. By contrast the $max operator applies only to the specified field, so this is generally not of use to you when you want documents from the grouping boundary as $last does.


    Considering the "last" example there and also removing the appropriate data from your examples then I get:

    {
        "_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
        }
    }
    

    Altered input is this:

    {
        "_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
    }
    

    Not bothering with correct ObjectId values in case as the hex string values are lexical just as the internal sort of an ObjectId would be anyway.

    Which are the "last" documents for each provided zone._id value from the collection, ordered by the original document _id value given.

    0 讨论(0)
  • 2021-01-15 14:40

    $last gives you the value of the last document which is processed by your grouping. You can not predict the order in which documents are processed, unless you sort the documents. So you don't get the results you expect.

    Try adding a $sort stage before your $group stage to get the documents in ascending date order:

    db.collection.aggregate(
       [
         { $sort: {
               "control_date":1
           }
         },
         {
           $group:
             {
               _id: "$zone._id",
               lastRegistered: { $last: "$_id" },
               zoneName:"$zone.zoneName",
               control_id:"$_id",
               actif:"$actif",
             }
         }
       ]
    )
    
    0 讨论(0)
提交回复
热议问题