2015-10-22 17 views
5

minimum querymaximum queryのサンプルデータセットを取得するクエリがあります。私の場合はproduct_1以下、product_2 ...MongoDB:ダイナミックフィールド名でネストしたオブジェクトの最小値、最大値を検索

{ 
    "_id" : NumberLong(540), 
    "product_1" : { 
      "orderCancelled" : 0, 
      "orderDelivered" : 6 
    }, 
    "product_2" : { 
      "orderCancelled" : 3, 
      "orderDelivered" : 16 
    }, 
    "product_3" : { 
      "orderCancelled" : 5, 
      "orderDelivered" : 11 
    } 
} 

のように私はフィールド名が動的であるモンゴでこれを行うことができますどのようにアイデアを得ていないのです名前は、ダイナミックされているフィールド、将来的には他のがあるかもしれない意味同じ製品の場合は、product_4product_5と作成されます。

は私がorderDelivered:16 & orderCancelled:0になります上記の文書の結果の例と同様に、orderCancelledのために私にorderDeliveredの最小値と最大値を与えるクエリを必要としています。
ありがとうございます。

+0

なぜあなたは配列にあなたの製品を入れないでください:利回りは

db.collection.aggregate([ { "$match": { "_id": 542 } }, { "$project": { "maxOrderCancelled": { "$max": { "$map": { "input": "$products", "as": "order", "in": "$$orc.orderCancelled" } } }, "minOrderDelivered": { "$min": { "$map": { "input": "$products", "as": "orc", "in": "$$orc.orderDelivered" } } } }} ]) 

? –

+0

@DmytroShevchenko私はあなたを得なかった。実際には別のケースでは、 'orderDelivered'のカウントを' product name'で与えることもできます。あなたのケースでデザインはどのようになりますか? – Shams

+0

私の答えにデータ構造の例を見てください。 'orderDelivered'を' product name'で数えることによって何を意味するのかを記述してください。 –

答えて

1

あなたはアレイに含まれるすべての製品ドキュメントのように、ドキュメントを再構築する必要があります

{ 
    "_id": NumberLong(540), 
    products: [ 
     { 
      "name": "product_1", 
      "orderCancelled": 0, 
      "orderDelivered": 6 
     }, 
     { 
      "name": "product_2", 
      "orderCancelled": 3, 
      "orderDelivered": 16 
     }, 
     { 
      "name": "product_3", 
      "orderCancelled": 5, 
      "orderDelivered": 11 
     } 
    ] 
} 

その後、あなたは、このような通常の最大/最小のクエリを発行することができるでしょう:

db.test.aggregate([ 
    { 
     $match: { "_id" : NumberLong(540) } 
    }, 
    { 
     $unwind: "$products" 
    }, 
    { 
     $group: { 
      _id: "$_id", 
      minDelivered: { $min: "$products.orderDelivered" }, 
      maxCancelled: { $max: "$products.orderCancelled" } 
     } 
    } 
]) 
+0

文書の構造を変更する方法はどうですか? – styvane

+2

@ user3100115既存のデータは、別のツールを使用して変更する必要があります。私はこのようなツールの議論はここで話題にならないと信じています。 –

+0

更新できません – styvane

2

あなたはそれらを更新して文書構造を変更する必要があります。 .forEachメソッドを使用して各文書をループする必要があります。$unsetすべてのフィールドの名前は、始まりがproduct_です。そこから、$set更新演算子を使用する製品の配列である新しいフィールドproductsを追加する必要があります。あなたはあなたの文書

var bulkOp = db.collection.initializeOrderedBulkOp(); 
var count = 0; 
db.collection.find().forEach(function(doc) { 
    var allproducts = []; 
    for(var key in doc) { 
     if(Object.prototype.hasOwnProperty.call(doc, key) && /^product_\d+/.test(key)) { 
      var product = {}; 
      product["name"] = key;  
      product["orderCancelled"] = doc[key]["orderCancelled"]; 
      product["orderDelivered"] = doc[key]["orderDelivered"]; 
      allproducts.push(product); 
      var unsetField = {}; 
      unsetField[key] = ""; 
      bulkOp.find({"_id": doc._id}).update({ "$unset": unsetField }); 
     }; 
     count++; 
    }; 
    bulkOp.find({"_id": doc._id}).update({ 
     "$set": { "products": allproducts } 
    }); 
    count++; 
    if(count % 500 === 0) { 
     // Execute per 500 operations and re-init 
     bulkOp.execute(); 
     bulkOp = db.collection.initializeOrderedBulkOp(); 
    } 
}) 

// clean up queues 

if(count > 0) { 
    bulkOp.execute(); 
} 

最大効率のためにドキュメントを更新する"bulk"操作を使用する必要があります言われていることは次のようになります:

{ 
     "_id" : NumberLong(542), 
     "products" : [ 
       { 
         "name" : "product_1", 
         "orderCancelled" : 0, 
         "orderDelivered" : 6 
       }, 
       { 
         "name" : "product_2", 
         "orderCancelled" : 3, 
         "orderDelivered" : 16 
       }, 
       { 
         "name" : "product_3", 
         "orderCancelled" : 5, 
         "orderDelivered" : 11 
       } 
     ] 
} 

その後、あなたの集計クエリが.aggregate()メソッドを使用しています:

db.collection.aggregate([ 
    { "$match": { "_id": 542 } }, 
    { "$unwind": "$products" }, 
    { "$group": { 
     "_id": "$_id", 
     "maxOrderCancelled": { "$max": "$products.orderCancelled"}, 
     "minOrderDelivvered": { "$min": "$products.orderDelivered"} 
    }} 
]) 

戻り値:

から
{ "_id" : NumberLong(542), "maxOrderCancelled" : 5, "minOrderDelivvered" : 6 } 

あなたがこれを行うにははるかに良い方法があるあなたの$project段階で$max$min使用することができますので、そこに最初の$unwindあなたの配列への必要はありません。

{ "_id" : NumberLong(542), "maxOrderCancelled" : 5, "minOrderDelivered" : 6 } 
関連する問題