我如何使用 mongodb 或 robomongo 计算价格正负价格?
How can i calculate price positive and negative price using mongodb or robomongo?
下面是我的用户定价收集数据
{
"_id" : ObjectId("584bc9ba420a6b189c510af6"),
"user_id" : 1,
"mobilenumber":"01234",
"price" : 2000.0,
"type" : "credit",
},
{
"_id" : ObjectId("584bc9ba420a6b189c510af6"),
"user_id" : 1,
"mobilenumber":"01234",
"price" : -1000.0,
"type" : "credit",
},
{
"_id" : ObjectId("584bc9ba420a6b189c3323w23"),
"user_id" : 2,
"mobilenumber":"04321",
"price" : 1000.0,
"type" : "credit",
}
这里我想计算所有用户的总正价和总负价,我需要检查该用户是否存在于摘要中 collection.if 记录不存在我们需要在摘要集合中创建文档如果它存在我们需要更新 "Totalpositiveprice"、"Totalnegativeprice" 和 "Balanceprice"
总结table这条记录已经存在
{
"user_id": "1",
"mobilenumber":"01234",
"Totalpositiveprice": 3000.0,
"Totalnegativeprice": 0,
"Balanceprice": 3000.0
},
{
"user_id": "3",
"mobilenumber":"05555",
"Totalpositiveprice": 1000.0,
"Totalnegativeprice": -100,
"Balanceprice": 900.0
}
我们需要更新文档 "mobilenumber":"01234",
我们需要为 "mobilenumber" 创建新文档:"04321",
"mobilenumber":"05555" 不需要做任何事情因为用户定价中没有任何东西
最后我应该得到这样的摘要集合
{
"user_id": "1",
"mobilenumber":"01234"
"Totalpositiveprice": 5000.0,
"Totalnegativeprice": -1000.0,
"Balanceprice": 4000.0
},
{
"user_id": "2",
"mobilenumber":"04321"
"Totalpositiveprice": 1000.0,
"Totalnegativeprice": 0,
"Balanceprice": 1000.0
},
{
"user_id": "3",
"mobilenumber":"05555",
"Totalpositiveprice": 1000.0,
"Totalnegativeprice": -100,
"Balanceprice": 900.0
}
您可以使用 conditional sum
完成此操作并使用 $out: collectionName
导出到另一个集合
可以试试:
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: 结果导出到 summary collection
与其他答案一样,$out
的问题在于它会替换 summary
集合(如果存在的话),而您可能不希望这样。您可以为此使用一点 JavaScript。
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 }
您可以尝试批量写入以批量上传从聚合结果创建的更新查询并更新 summary
集合。
这是一个快速代码,您可以从 Mongo shell 中尝试,您可以根据自己的需要进行调整。
下面的代码查询 user_id
并根据聚合值增加价格值,如果找不到匹配的 user_id 则更新。
您应该根据需要更改 batch
。
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();
}
无论您想做什么,都涉及复杂的查询。请参阅以下查询。我先解释一下。
1- 第一个管道 $group
对你来说很明显。
需要 2 秒管道 $lookup
才能生成您想要的结果,因为您希望将当前价格和已经汇总的价格编译到一个文档中。
3- 第三阶段只是展开数组 summary
我们已经查找以便我们能够编译价格。
4-第四$project
阶段是做你真正想做的,也就是说它是在编译总结文档你就能看懂。
5- 生成摘要集合。
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"}
])
下面是我的用户定价收集数据
{
"_id" : ObjectId("584bc9ba420a6b189c510af6"),
"user_id" : 1,
"mobilenumber":"01234",
"price" : 2000.0,
"type" : "credit",
},
{
"_id" : ObjectId("584bc9ba420a6b189c510af6"),
"user_id" : 1,
"mobilenumber":"01234",
"price" : -1000.0,
"type" : "credit",
},
{
"_id" : ObjectId("584bc9ba420a6b189c3323w23"),
"user_id" : 2,
"mobilenumber":"04321",
"price" : 1000.0,
"type" : "credit",
}
这里我想计算所有用户的总正价和总负价,我需要检查该用户是否存在于摘要中 collection.if 记录不存在我们需要在摘要集合中创建文档如果它存在我们需要更新 "Totalpositiveprice"、"Totalnegativeprice" 和 "Balanceprice"
总结table这条记录已经存在
{
"user_id": "1",
"mobilenumber":"01234",
"Totalpositiveprice": 3000.0,
"Totalnegativeprice": 0,
"Balanceprice": 3000.0
},
{
"user_id": "3",
"mobilenumber":"05555",
"Totalpositiveprice": 1000.0,
"Totalnegativeprice": -100,
"Balanceprice": 900.0
}
我们需要更新文档 "mobilenumber":"01234",
我们需要为 "mobilenumber" 创建新文档:"04321",
"mobilenumber":"05555" 不需要做任何事情因为用户定价中没有任何东西
最后我应该得到这样的摘要集合
{
"user_id": "1",
"mobilenumber":"01234"
"Totalpositiveprice": 5000.0,
"Totalnegativeprice": -1000.0,
"Balanceprice": 4000.0
},
{
"user_id": "2",
"mobilenumber":"04321"
"Totalpositiveprice": 1000.0,
"Totalnegativeprice": 0,
"Balanceprice": 1000.0
},
{
"user_id": "3",
"mobilenumber":"05555",
"Totalpositiveprice": 1000.0,
"Totalnegativeprice": -100,
"Balanceprice": 900.0
}
您可以使用 conditional sum
完成此操作并使用 $out: collectionName
可以试试:
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: 结果导出到 summary collection
与其他答案一样,$out
的问题在于它会替换 summary
集合(如果存在的话),而您可能不希望这样。您可以为此使用一点 JavaScript。
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 }
您可以尝试批量写入以批量上传从聚合结果创建的更新查询并更新 summary
集合。
这是一个快速代码,您可以从 Mongo shell 中尝试,您可以根据自己的需要进行调整。
下面的代码查询 user_id
并根据聚合值增加价格值,如果找不到匹配的 user_id 则更新。
您应该根据需要更改 batch
。
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();
}
无论您想做什么,都涉及复杂的查询。请参阅以下查询。我先解释一下。
1- 第一个管道 $group
对你来说很明显。
需要 2 秒管道 $lookup
才能生成您想要的结果,因为您希望将当前价格和已经汇总的价格编译到一个文档中。
3- 第三阶段只是展开数组 summary
我们已经查找以便我们能够编译价格。
4-第四$project
阶段是做你真正想做的,也就是说它是在编译总结文档你就能看懂。
5- 生成摘要集合。
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"}
])