在Mongo上插入/更新汇总数据

时间:2018-12-31 03:40:36

标签: mongodb mongodb-query aggregation-framework

请考虑以下集合:

请求->

{
  _id : ObjectId("573f28f49b0ffc283676f736"),
  date : '2018-12-31',
  userId: ObjectId("5c1239e93a7b9a72ef1c9197"),
  serviceId: ObjectId("572e29b0116b5db3057bd821"),
  status: 'completed'
} 

我对请求集合进行了汇总操作,该操作返回以下格式的文档:

{
    "grossRequests" : 2,
    "grossData" : [ 
        {
            "date" : "2018-08-04",
            "count" : 1,
            "requests" : [ 
                ObjectId("5b658147c73beb5ea3debc6e")
            ]
        }, 
        {
            "date" : "2018-08-05",
            "count" : 1,
            "requests" : [ 
                ObjectId("5b658160572faa5dd033fb48")
            ]
        }
    ],
    "netData" : [ 
        {
            "date" : "2018-08-05",
            "count" : 1,
            "requests" : [ 
                ObjectId("5b658160572faa5dd033fb48")
            ]
        }
    ],
    "netRequests" : 1.0,
    "userId" : ObjectId("5c1239e93a7b9a72ef1c9197"),
    "serviceId" : "572e29b0116b5db3057bd821"
}

上方是要插入 cumulativeData

中的文档

现在,我需要将聚合操作返回的所有文档添加到名为 cumulativeData 的集合中。

cumulativeData 集合具有一个文档,每个服务类型的每个用户ID

我正在查询特定的日期范围,并将其插入到集合中时,想“合并”文档,而不是替换它们。

例如,如果我使用forEach遍历聚合操作返回的所有文档,则对于每个新文档,我都会得到{{userId,serviceType}对,它在 cumulativeData 集合),我需要按原样插入它,对于集合中已经存在的每个文档,我都需要按以下方式进行更新。

grossRequests -> add both values
grossData -> push the new values into the existing set
netData -> push the new values into the existing set
netRequests -> add both values

操作如下,

**累积数据**中的现有文档

{
    "grossRequests": 2,
    "grossData": [{
            "date": "2018-08-04",
            "count": 1,
            "requests": [
                ObjectId("5b658147c73beb5ea3debc6e")
            ]
        }, {
            "date": "2018-08-05",
            "count": 1,
            "requests": [
                ObjectId("5b658160572faa5dd033fb48")
            ]
        }
    ],
    "netData": [{
            "date": "2018-08-05",
            "count": 1,
            "requests": [
                ObjectId("5b658160572faa5dd033fb48")
            ]
        }
    ],
    "netRequests": 1,
    "userId": ObjectId("5c1239e93a7b9a72ef1c9197"),
    "serviceId": "572e29b0116b5db3057bd821"
}

在新日期范围内汇总后生成的新文档

{
    "grossRequests": 2,
    "grossData": [{
            "date": "2018-08-04",
            "count": 1,
            "requests": [
                ObjectId("5b658147c73beb5ea3debc8e")
            ]
        }, {
            "date": "2018-08-05",
            "count": 1,
            "requests": [
                ObjectId("5b658160572faa5dd033fb4l")
            ]
        }
    ],
    "netData": [{
            "date": "2018-08-05",
            "count": 1,
            "requests": [
                ObjectId("5b658160572faa5dd033fb4l")
            ]
        }
    ],
    "netRequests": 1,
    "userId": ObjectId("5c1239e93a7b9a72ef1c9197"),
    "serviceId": "572e29b0116b5db3057bd821"
}

最终结果

{
    "grossRequests": 4,
    "grossData": [{
            "date": "2018-08-04",
            "count": 2,
            "requests": [
                ObjectId("5b658147c73beb5ea3debc6e") , ObjectId("5b658147c73beb5ea3debc8e")
            ]
        }, {
            "date": "2018-08-05",
            "count": 2,
            "requests": [
                ObjectId("5b658160572faa5dd033fb48"), ObjectId("5b658160572faa5dd033fb4l")
            ]
        }
    ],
    "netData": [{
            "date": "2018-08-05",
            "count": 2,
            "requests": [
                ObjectId("5b658160572faa5dd033fb48"),ObjectId("5b658160572faa5dd033fb4l")
            ]
        }
    ],
    "netRequests": 2,
    "userId": ObjectId("5c1239e93a7b9a72ef1c9197"),
    "serviceId": "572e29b0116b5db3057bd821"
}

1 个答案:

答案 0 :(得分:1)

您可以使用以下代码执行更新。

当未找到具有用户ID /服务ID的记录时,涉及两个步骤:第一步插入数据,否则更新数据。

在更新步骤中,首先更新顶部字段,即count,然后迭代netData和grossData以执行合并。

要执行合并,我们使用具有n个修改计数的writersult来标识是否必须更新数组值或插入新的数组值。

您可以调整以下查询以满足您的需求。

db.getCollection('requests').aggregate(your aggregation query).forEach(function(doc) {
var user_id = doc.userId;
var service_id = doc.serviceId;
var gross_requests = doc.grossRequests;
var net_requests = doc.netRequests;
var gross_data = doc.grossData;
var net_data = doc.netData;

var matched = db.getCollection('cumulativeData').findOne({
    "userId": user_id,
    serviceId: service_id
});
if (matched == null) {
    db.getCollection('cumulativeData').insert(doc);
} else {
    db.getCollection('cumulativeData').update({
        "userId": user_id,
        serviceId: service_id
    }, {
        $inc: {
            "grossRequests": gross_requests,
            "netRequests": net_requests
        }
    });
    gross_data.forEach(function(grdoc) {
        var writeresult = db.getCollection('cumulativeData').update({
            "userId": user_id,
            serviceId: service_id,
            "grossData.date": grdoc.date
        }, {
            $inc: {
                "grossData.$.count": grdoc.count
            },
            $push: {
                "grossData.$.requests": {
                    $each: grdoc.requests
                }
            }
        });
        if (writeresult.nModified == 0) {
            db.getCollection('cumulativeData').update({
                "userId": user_id,
                serviceId: service_id
            }, {
                $push: {
                    "grossData": {
                        "count": grdoc.count,
                        "requests": grdoc.requests,
                        "date": grdoc.date
                    }
                }
            });
        }
    });
    net_data.forEach(function(nrdoc) {
        var writeresult = db.getCollection('cumulativeData').update({
            "userId": user_id,
            serviceId: service_id,
            "netData.date": nrdoc.date
        }, {
            $inc: {
                "netData.$.count": nrdoc.count
            },
            $push: {
                "netData.$.requests": {
                    $each: nrdoc.requests
                }
            }
        });
        if (writeresult.nModified == 0) {
            db.getCollection('cumulativeData').update({
                "userId": user_id,
                serviceId: service_id
            }, {
                $push: {
                    "netData": {
                        "count": nrdoc.count,
                        "requests": nrdoc.requests,
                        "date": nrdoc.date
                    }
                }
            });
        }
    });
}

});