How can i calculate price positive and negative price using mongodb or robomongo?

你离开我真会死。 提交于 2019-11-29 13:02:08

You can try bulk write to bulk upload the update queries created from aggregation result and update the summary collection.

Here is a quick code that you can try from Mongo shell and you can adjust to your needs.

The below code queries for user_id and increments the price values based on the aggregation values and upserts if no matching user_id is found.

You should change the batch based on your needs.

var bulk = db.getCollection('summary').initializeUnorderedBulkOp();
var count = 0;
var batch = 1;

db.getCollection('userpricing').aggregate([
    {$group: {
        _id:"$user_id", 
        Totalpositiveprice:{$sum:{$cond:[{ '$gt': ['$price', 0]}, "$price", 0]}}, 
        Totalnegativeprice:{$sum:{$cond:[{ '$lt': ['$price', 0]}, "$price", 0]}},
        Balanceprice:{"$sum":"$price"}}
     },
    {$project: {_id:0, user_id:"$_id", Totalpositiveprice:1, Totalnegativeprice:1, Balanceprice:1}}
]).forEach(function(doc){ 
    var user_id = doc.user_id; 
    var totalpositiveprice = doc.Totalpositiveprice; 
    var totalnegativeprice = doc.Totalnegativeprice; 
    var balanceprice = doc.Balanceprice; 
    bulk.find({ "user_id" : user_id }).upsert().updateOne(
      { $inc: {"Totalpositiveprice" : totalpositiveprice, "Totalnegativeprice" : totalnegativeprice, "Balanceprice" : balanceprice } }
   ); 
    count++;  
    if (count == batch) { 
        bulk.execute(); 
        bulk = db.getCollection('summary').initializeUnorderedBulkOp(); 
        count = 0;
    } 
});

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

You can do it by using conditional sum and export in another collection use $out: collectionName

can try it :

db.getCollection('userpricing').aggregate([
    {$group: {
        _id:"$user_id", 
        user_id: {$first: "$user_id"}, 
        Totalpositiveprice:{$sum:{$cond:[{ '$gt': ['$price', 0]}, "$price", 0]}}, 
        Totalnegativeprice:{$sum:{$cond:[{ '$lt': ['$price', 0]}, "$price", 0]}},
        Balanceprice:{"$sum":"$price"}}
     },
     {$project: {_id:0, user_id:1, Totalpositiveprice:1, Totalnegativeprice:1, Balanceprice:1}},
     {$out: "summary"}
])

N.B: result exported in summary collection

Whatever you want to do involves a complex query. See the below query. Let me explain it first.

1- first pipeline $group is obvious to you.

2- second pipeline $lookup is required to generate your desired result as you want that the current prices and the already summarized prices should be compiled into one document.

3- third stage is just unwinding the array summary we have looked up so that we will be able to compile the prices.

4- fourth $project stage is doing what you really want to do that is to say that it is compiling the summary document you will be able to understand it.

5- generating the summary collection.

db.getCollection('userpricing').aggregate([
     {$group:{
            _id:"$user_id",
            Totalpositiveprice:{$sum:{$cond:{if:{ $gt:["$price",0]}, then: "$price", else: 0}}},
            Totalnegativeprice:{$sum:{$cond:{if:{ $lt:["$price",0]}, then: "$price", else: 0}}},
            Balanceprice:{"$sum":"$price"}
     }},
     {
      $lookup:
        {
          from: "summary",
          localField: "_id",
          foreignField: "user_id",
          as: "summary"
        }
     },
     {$unwind:{path:"$summary", preserveNullAndEmptyArrays:true}},
     {$project:{
         _id:0,
         user_id:"$_id",
         Balanceprice:{$add:["$Balanceprice", {$cond:{if:{ $eq:["$summary",undefined]}, then: 0, else: "$summary.Balanceprice"}}]},
         Totalnegativeprice:{$add:["$Totalnegativeprice", {$cond:{if:{ $eq:["$summary",undefined]}, then: 0, else: "$summary.Totalnegativeprice"}}]},
         Totalpositiveprice:{$add:["$Totalpositiveprice", {$cond:{if:{ $eq:["$summary",undefined]}, then: 0, else: "$summary.Totalpositiveprice"}}]}
     }},
   {$out:"summary"}  
])

As from other answers, the problem with $out is that it will replace the summary collection if one exists and you may not want that. You can use a little JavaScript for that.

var cursor = db.userpricing.aggregate([
  {
    $group : {
      _id : "$user_id",
      Totalpositiveprice : {
        $sum : {
          $cond : {
            if: { $gte : ["$price" , 0]},
            then : "$price",
            else : 0
          }
        }
      },
      Totalnegativeprice : {
        $sum : {
          $cond : {
            if: {$lte : ["$price" , 0]},
            then : "$price",
            else : 0
          }
        }
      },
      Balanceprice : {$sum : "$price"}
    }
  },
  {
    $project : {
      _id : 0,
      user_id : "$_id",
      Totalpositiveprice : 1,
      Totalnegativeprice : 1,
      Balanceprice : 1
    }
  }
]);

while(cursor.hasNext()) {
  var elem = cursor.next();
  db.summary.update(
    {user_id : elem.user_id},
    elem,
    {upsert : true}
  );
}



> db.summary.find()
{ "_id" : ObjectId("58564bb71e2cb47f2ddcf1b4"), "Totalpositiveprice" : 10000, "Totalnegativeprice" : 0, "Balanceprice" : 10000, "user_id" : 2 }
{ "_id" : ObjectId("58564bb71e2cb47f2ddcf1b5"), "Totalpositiveprice" : 20000, "Totalnegativeprice" : -10000, "Balanceprice" : 10000, "user_id" : 1 }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!