2015-04-27 5 views
2

Вопрос: Допустим, у меня есть следующие объекты в коллекции:Query коллекция для последнего уникального объекта

Как бы я вернуть один рекорд за "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") 
    } 
} 

ответ

1

Вам нужен aggregation pipeline что первый сортирует документы в коллекции от номера версии нисходящих с использованием $sort, затем группирует упорядоченные документы по product_id с помощью оператора $group. В группировке использовать $first оператор на $$ROOT возвратить первый документ в отсортированной группы:

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); // 
}); 

Console Output:

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

- UPDATE -

Чтобы проецировать полный документ, замените трубопровод $project на t он следующее:

{ 
    "$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 
} 
+0

Спасибо, что попробуй. – Fostah

+0

Есть ли способ проецировать полный объект без указания каждого ключа/значения? – Fostah

+0

@Fostah Да, вы можете спроектировать новое поле, которое содержит весь документ из предыдущей групповой операции, иначе вам нужно будет указать новые поля со специфическими свойствами. Я обновил свой ответ на этот счет. – chridam

2

Похоже, что работа для Mongo's aggregation framework. Вы можете экстраполировать с this example как подойти к проблеме.

Update: Для того, чтобы получить один за 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 
    }} 
]); 
+0

Спасибо плохо дать ему попробовать и обновить этот вопрос. – Fostah

Смежные вопросы