在集合中查询最新的唯一对象
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
}
问题: 假设我在集合中有以下对象:
我如何 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
}