Mongodb Quer ie получить пики временных рядов - PullRequest
0 голосов
/ 17 февраля 2020

У меня есть mongodb с данными некоторых датчиков. Каждый раз, когда датчик срабатывает, значение увеличивается на 1. Иногда датчик сбрасывается. Теперь я хочу суммировать значения данных датчика, чтобы получить общее значение временных рядов.

Мои данные выглядят так:

{
    value: 10
    timestamp: 1577836800
}, {
    value: 12
    timestamp: 1577836810
}, {
    value: 17 <== PEAK
    timestamp: 1577836820
}, {
    value: 2
    timestamp: 1577836830
}, {
    value: 7
    timestamp: 1577836840
}, {
    value: 10 <== PEAK
    timestamp: 1577836850
},{
    value: 1
    timestamp: 1577836860
}

Моя цель - получить все значения из пиков (17 + 10), в пределах минимальной и максимальной отметки времени, и суммируйте их (это также может быть сделано вручную впоследствии). Это означало бы, что я должен отсортировать их по метке времени и сравнить значение с предыдущим, чтобы проверить, какое из них выше. Я новичок в понедельник go и не знаю с чего начать. Любая помощь приветствуется!

1 Ответ

0 голосов
/ 17 февраля 2020

Я упомянул в комментарии об использовании периферийного устройства, которое позволяет назначить значение на соответствующий период. Используйте сервис nodeJS, чтобы выяснить, какой документ необходимо обновить, поскольку это делает запрос к коллекции намного проще и быстрее.

Вы можете использовать этот формат для каждого документа:

{
    "period" : {
        "start" : 1577836800,
        "end" : 1577836820
    },
    "values": [
        {
            "value": 10
            "timestamp": 1577836800
        }, 
        {
            "value": 12
            "timestamp": 1577836810
        }, 
        {
            "value": 17
            "timestamp": 1577836820
        }
    ]
}

Как пример, когда датчик предоставляет сервису новое значение. В этом случае значение 2, получите последний документ и сравните его с последним значением в пределах значений.

если новое значение меньше предыдущего значения, создайте новый документ со следующей информацией и, конечно же, не забудьте обновить предыдущий документ, заполнив "periode.end" последним значением отметка времени.

{
    "period" : {
        "start" : 1577836830,
        "end" : null
    },
    "values": [
        {
            "value": 2
            "timestamp": 1577836830
        }
    ]
}

ОБНОВЛЕНИЕ

Я написал этот сценарий JavaScript для миграции из одной коллекции, обработки данных в новом формате на основе требований и вставьте их в новую коллекцию.

function createSensorObject(start, value){
    var doc = new Object();

    doc.period = new Object();
    doc.period["start"] = start;
    doc.period["end"] = null;

    doc.values = new Array();

    var valueObject = new Object();
    valueObject["value"] = value;
    valueObject["timestamp"] = start;

    doc.values.push(valueObject);
    return doc;
}

function pushNewValueIntoSensorObject(doc, value, timestamp){
    doc["period"]["end"] = timestamp;

    var valueObject = new Object();
    valueObject["value"] = value;
    valueObject["timestamp"] = timestamp;

    doc["values"].push(valueObject);
}

function closePeriodInSensorObject(doc) {
    doc["period"]["end"] = doc["period"]["start"];
}

// New collection cursor to insert new values.
var sensorNewCursor = db.sensor_new; 

// Using the aggregate pipeline to sort and using toArray to iterate through.
var sensorDocuments = db.sensor.aggregate([ { $sort: { "timestamp" : 1}}]).toArray();

// Temp array to store the new sensor objects.
var sensorObjectArray = new Array();

for(var i = 0; i < sensorDocuments.length; i++) {
    // Working with the current document.
    var currentDocument = sensorDocuments[i];
    var value = currentDocument["value"];
    var timestamp = currentDocument["timestamp"];

    // Initially creating a new document.
    if(i === 0) {
        var sensorObject = createSensorObject(timestamp, value);

        // If there is only one document then we need to close the document.
        if(i === (sensorDocuments.Length - 1)) {
            closePeriodInSensorObject(sensorObject);
        }

        // Push into temp array.
        sensorObjectArray.push(sensorObject);
    }
    else{   
        // Get the previous value.
        var previousValue = sensorDocuments[i - 1]["value"];

        // Get the latest sensor object from the temp array.
        var sensorObject = sensorObjectArray[sensorObjectArray.length - 1];

        // When the new value is larger or equal to the previous value.
        if(value >= previousValue) {
            // Push the new value into the latest sensor object.
            pushNewValueIntoSensorObject(sensorObject, value, timestamp);
        }
        else {  
            // Create new sensor object.
            var sensorObject = createSensorObject(timestamp, value);
            sensorObjectArray.push(sensorObject);
        }
    }
}

print(`Inserting ${sensorObjectArray.length} objects into the db.sensor_new collection.`);

// Insert the whole array into the new collection
sensorNewCursor.insert(sensorObjectArray);

Вы можете использовать функцию load для вызова этого js файла из mongoshell. https://docs.mongodb.com/manual/reference/method/load/


Посмотрите на два снимка экрана.

Original data

New data


Наконец-то! Запрос

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

Сначала нам нужно развернуть значения, затем $ group с $ max, чтобы найти наше максимальное значение, а затем снова сгруппировать, но без поля $ _id для суммирования значений.

db.collection.aggregate([
    {
        $unwind: "$values"
    },
    {
        $group: {
            "_id": "$_id",
            "value": {
                $max: "$values.value"
            }
        }
    },
    {
        $group: {
            "_id": null,
            "total": {
                $sum: "$value"
            }
        }
    }
])

Результатом этого запроса будет 28

[
    {
        "_id": null,
        "total": 28
    }
]

MongoPlayground в соответствии с новым структура документа: https://mongoplayground.net/p/WblN5QzPoeB

Я действительно надеюсь, что это работает с вашей стороны, если вы не прокомментируете. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...