在集合中查询最新的唯一对象

Query a collection for the latest unique object

问题: 假设我在集合中有以下对象:

我如何 return 每个 "product_id" 一条记录,并且只有 "version" 数字最大的一条记录?这可以在猫鼬中完成吗?

{
    "_id" : ObjectId("54f765564b10883c1800002a"),
    "total_invoice_fob_case" : 86.70999999999999,
    "status" : "Draft",
    "discount" : "3.40",
    "effective_date" : ISODate("2013-08-01T06:00:00.000Z"),
    "version" : 2,
    "controlstate" : "AB",
    "controlstate_id" : ObjectId("54d510e9e3d793f581b6bb27"),
    "product" : "Product A",
    "product_id" : ObjectId("54f75b5e4b1088801a000627"),
    "size" : "1.75LTR",
    "size_id" : ObjectId("5418a3dd750b4294c2cb3a47"),
    "vendor" : "BEAM SUNTORY",
    "vendor_id" : ObjectId("54ef5aa74b1088781b000169"),
    "product_state_code" : "123",
    "net_fob_cost" : 86.70999999999999,
    "change_reason" : [ 
        "Other"
    ],
    "submitted" : {
        "submitted_date" : ISODate("2014-05-16T06:00:00.000Z")
    }
},
{
    "_id" : ObjectId("54f765564b10883c1800002b"),
    "total_invoice_fob_case" : 86.70999999999999,
    "status" : "Draft",
    "discount" : "4.40",
    "effective_date" : ISODate("2013-08-01T06:00:00.000Z"),
    "version" : 3,
    "controlstate" : "AB",
    "controlstate_id" : ObjectId("54d510e9e3d793f581b6bb27"),
    "product" : "Product A",
    "product_id" : ObjectId("54f75b5e4b1088801a000627"),
    "size" : "1.75LTR",
    "size_id" : ObjectId("5418a3dd750b4294c2cb3a47"),
    "vendor" : "BEAM SUNTORY",
    "vendor_id" : ObjectId("54ef5aa74b1088781b000169"),
    "product_state_code" : "123",
    "net_fob_cost" : 86.70999999999999,
    "change_reason" : [ 
        "Other"
    ],
    "submitted" : {
        "submitted_date" : ISODate("2014-05-16T06:00:00.000Z")
    }
},
{
    "_id" : ObjectId("54f765564b10883c1800002c"),
    "total_invoice_fob_case" : 86.70999999999999,
    "status" : "Draft",
    "discount" : "3.40",
    "effective_date" : ISODate("2013-08-01T06:00:00.000Z"),
    "version" : 2,
    "controlstate" : "AB",
    "controlstate_id" : ObjectId("54d510e9e3d793f581b6bb27"),
    "product" : "Product B",
    "product_id" : ObjectId("54f75b5e4b1088801a000628"),
    "size" : "1.75LTR",
    "size_id" : ObjectId("5418a3dd750b4294c2cb3a47"),
    "vendor" : "BEAM SUNTORY",
    "vendor_id" : ObjectId("54ef5aa74b1088781b000169"),
    "product_state_code" : "123",
    "net_fob_cost" : 86.70999999999999,
    "change_reason" : [ 
        "Other"
    ],
    "submitted" : {
        "submitted_date" : ISODate("2014-05-16T06:00:00.000Z")
    }
}

听起来像是 Mongo 的 aggregation framework. You can extrapolate from this example 如何解决问题的工作。

更新:要检索每个 product_id 的最高版本,您还需要使用 $first:

db.products.aggregate([
  {$sort: {product_id: 1, version: -1}}, // sort first so that $first pulls the correct record
  {$group: {
    _id: {product_id: '$product_id'}, // group by the product_id
    product: {$first: $$ROOT} // only return the first document per group
  }}
]);

您需要 aggregation pipeline that first sorts the documents in the collection by version number descending using a $sort pipeline stage, then groups the ordered documents by product_id using the $group operator. Within the grouping use the $first 运算符 $$ROOT 到 return 已排序组中的第一个文档:

var pipeline = [
    {
        "$sort": { "version": -1 }
    },
    {
        "$group": {
            "_id": "$product_id",
            "value": {
                "$first": "$$ROOT"
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "product_id": "$_id",
            "status": "$value.status",
            "version": "$value.version",
            "product" : "$value.product"
        }    
    }
 ];

// Mongoose aggregation
Model.aggregate(pipeline, function (err, res) {
  if (err) return handleError(err);
  console.log(res); // 
});

控制台输出:

[ 
    {
        "product_id" : ObjectId("54f75b5e4b1088801a000628"),
        "status" : "Draft",
        "version" : 2,
        "product" : "Product B"
    }, 
    {
        "product_id" : ObjectId("54f75b5e4b1088801a000627"),
        "status" : "Draft",
        "version" : 3,
        "product" : "Product A"
    }
]

-- 更新 --

要投影完整文档,请将 $project 管道替换为以下内容:

{
    "$project": {
        "_id": 0,
        "product": "$value"
    }
}

输出:

/* 1 */
{
    "result" : [ 
        {
            "product" : {
                "_id" : ObjectId("54f765564b10883c1800002c"),
                "total_invoice_fob_case" : 86.7099999999999940,
                "status" : "Draft",
                "discount" : "3.40",
                "effective_date" : ISODate("2013-08-01T06:00:00.000Z"),
                "version" : 2,
                "controlstate" : "AB",
                "controlstate_id" : ObjectId("54d510e9e3d793f581b6bb27"),
                "product" : "Product B",
                "product_id" : ObjectId("54f75b5e4b1088801a000628"),
                "size" : "1.75LTR",
                "size_id" : ObjectId("5418a3dd750b4294c2cb3a47"),
                "vendor" : "BEAM SUNTORY",
                "vendor_id" : ObjectId("54ef5aa74b1088781b000169"),
                "product_state_code" : "123",
                "net_fob_cost" : 86.7099999999999940,
                "change_reason" : [ 
                    "Other"
                ],
                "submitted" : {
                    "submitted_date" : ISODate("2014-05-16T06:00:00.000Z")
                }
            }
        }, 
        {
            "product" : {
                "_id" : ObjectId("54f765564b10883c1800002b"),
                "total_invoice_fob_case" : 86.7099999999999940,
                "status" : "Draft",
                "discount" : "4.40",
                "effective_date" : ISODate("2013-08-01T06:00:00.000Z"),
                "version" : 3,
                "controlstate" : "AB",
                "controlstate_id" : ObjectId("54d510e9e3d793f581b6bb27"),
                "product" : "Product A",
                "product_id" : ObjectId("54f75b5e4b1088801a000627"),
                "size" : "1.75LTR",
                "size_id" : ObjectId("5418a3dd750b4294c2cb3a47"),
                "vendor" : "BEAM SUNTORY",
                "vendor_id" : ObjectId("54ef5aa74b1088781b000169"),
                "product_state_code" : "123",
                "net_fob_cost" : 86.7099999999999940,
                "change_reason" : [ 
                    "Other"
                ],
                "submitted" : {
                    "submitted_date" : ISODate("2014-05-16T06:00:00.000Z")
                }
            }
        }
    ],
    "ok" : 1
}