假设我有一个像这样的数据集:
yearMonth | amount
201908 | 100
201909 | 100
201910 | 200
201911 | 100
201912 | 200
202001 | 300
202002 | 200
有没有一种方法可以对通过记录进行求和/累加以获得类似这样的结果集:
yearMonth | amount | balance
201908 | 100 | 100
201909 | 100 | 200
201910 | 200 | 400
201911 | 100 | 500
201912 | 200 | 700
202001 | 300 | 1000
202002 | 200 | 1200
答案 0 :(得分:0)
尝试以下聚合查询:
db.collection.aggregate([
/** Sort on entire collection is not preferred, but you need it if 'yearMonth' field is not ordered */
/** Group on empty & push all docs to 'data' array */
{ $group: { _id: "", data: { $push: "$$ROOT" } } },
{
$project: {
data: {
$let: {
vars: {
data: {
$reduce: {
input: "$data", /** Iterate over 'data' array & push newly formed docs to docs array */
initialValue: { amount: 0, docs: [] },
in: {
docs: {
$concatArrays: [
"$$value.docs",
[
{
_id: "$$this._id",
yearMonth: "$$this.yearMonth",
amount: "$$this.amount",
balance: {
$add: ["$$value.amount", "$$this.amount"],
},
},
],
],
},
amount: { $add: ["$$value.amount", "$$this.amount"] },
},
},
},
},
in: "$$data.docs", /** Return only 'docs' array & ignore 'amount' field */
},
},
},
},
/** unwind 'data' array(newly formed 'data' array field) */
{
$unwind: "$data",
},
/** Replace data object as new root for each document in collection */
{
$replaceRoot: {
newRoot: "$data",
},
},
]);
答案 1 :(得分:0)
在此mapReduce的指导下使用answer收集方法,您可以获得所需的结果。
这是使用以下选项的pymongo解决方案:
这是python(pymongo)代码:
from pymongo import MongoClient
from bson.code import Code
client = MongoClient()
db = client.tst1
coll = db.mapr1
map1 = Code('''
function () {
emit(
this.yearMonth,
this.amount
);
}
''')
reduce1 = Code('''
function (key, values) {
return value;
}
''')
fin1 = Code('''
function(key, value) {
total += value;
return {amount: value, balance: total};
}
''')
result = coll.map_reduce(map1, reduce1, out={'inline': 1}, scope={'total': 0}, finalize=fin1)
for doc in result['results']:
print(f'The doc is {doc}')
结果:
The doc is {'_id': 201908.0, 'value': {'amount': 100.0, 'balance': 100.0}}
The doc is {'_id': 201909.0, 'value': {'amount': 100.0, 'balance': 200.0}}
The doc is {'_id': 201910.0, 'value': {'amount': 200.0, 'balance': 400.0}}
The doc is {'_id': 201911.0, 'value': {'amount': 100.0, 'balance': 500.0}}
The doc is {'_id': 201912.0, 'value': {'amount': 200.0, 'balance': 700.0}}
The doc is {'_id': 202001.0, 'value': {'amount': 300.0, 'balance': 1000.0}}
The doc is {'_id': 202002.0, 'value': {'amount': 200.0, 'balance': 1200.0}}
收藏中的文件
{'_id': ObjectId('5e89c410b187b1e1abb089af'),
'amount': 100,
'yearMonth': 201908}
{'_id': ObjectId('5e89c410b187b1e1abb089b0'),
'amount': 100,
'yearMonth': 201909}
{'_id': ObjectId('5e89c410b187b1e1abb089b1'),
'amount': 200,
'yearMonth': 201910}
{'_id': ObjectId('5e89c410b187b1e1abb089b2'),
'amount': 100,
'yearMonth': 201911}
{'_id': ObjectId('5e89c410b187b1e1abb089b3'),
'amount': 200,
'yearMonth': 201912}
{'_id': ObjectId('5e89c410b187b1e1abb089b4'),
'amount': 300,
'yearMonth': 202001}
{'_id': ObjectId('5e89c410b187b1e1abb089b5'),
'amount': 200,
'yearMonth': 202002}