Вставка / обновление агрегированных данных в Mongo - PullRequest
0 голосов
/ 31 декабря 2018

Рассмотрим следующую коллекцию:

запросы ->

{
  _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 содержит один документ на идентификатор пользователя для serviceType .

Я выполняюзапрашивать определенные диапазоны дат и, вставляя их в коллекцию, хотел бы «объединить» документы, а не заменить их.

так, например, если я перебираю все документы, возвращенные агрегациейоперация с использованием forEach, для каждого нового документа, который я получаю (пара {userId,serviceType}, которой нет в коллекции cumulativeData ), мне нужно вставить ее как есть и для каждого документа, которыйh уже присутствует в коллекции, мне нужно обновить его следующим образом.

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

Операция будет выглядеть следующим образом:

Существующий документ в ** cumulativeData **

{
    "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 голосов
/ 02 января 2019

Вы можете использовать приведенный ниже код для выполнения обновлений.

Первый этап состоит из двух шагов, когда запись с идентификатором пользователя / идентификатора службы не найдена, вставьте данные, иначе обновите данные.

На первом этапе обновления первое обновлениеверхние поля, т.е. число, за которым следуют итерации netData и grossData для выполнения слияния.

Для выполнения слияния мы используем writeresult с nmodified count, чтобы определить, нужно ли нам обновлять значение массива или вставлять новое значение массива.

Вы можете настроить ниже запрос для удовлетворения ваших потребностей.

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
                    }
                }
            });
        }
    });
}

});

...