Mongodb时间序列操作和生成

时间:2014-09-27 06:06:47

标签: mongodb time-series

我有一个带有这种文档的Mongodb Collection:

{
"_id" : ObjectId("53cb898bed4bd6c24ae07a9f"),
"account" : "C1"
"created_on" : ISODate("2014-10-01T01:23:00.000Z")
"value" : 253
}

{
"_id" : ObjectId("52cb898bed4bd6c24ae06a9e"),
"account" : "C2"
"created_on" : ISODate("2014-10-01T01:23:00.000Z")
"value" : 9381
}

C1和C2每分钟都有一份文件。

我想为其他帐户生成数据“C0”,它将等于:(C2 - C1)* 0.25 因此,目标是为集合中的每分钟生成数据。

根据你的说法,是否有可能在mongo shell中做到这一点?

非常感谢:)

1 个答案:

答案 0 :(得分:2)

解决此问题的逻辑如下:

 a) group all the records by created_on date.
 b) get the value of both the documents in each group.
 c) calculate the difference the C2 and C1 documents for each group.
 d) In case one of the documents is missing difference 
    would be the value of the existing document.
 d) project a document with value as (difference*.25) in each group.
 e) insert the projected document to the collection.

我想提出两个解决方案,第一个是您的假设,

  

C1和C2每分钟都有一个文件。

所以for every created_on时间,会有only two个文档,C1C2

db.time.aggregate([ {
    $match : {
        "account" : {
            $in : [ "C1", "C2" ]
        }
    }
}, {
    $group : {
        "_id" : "$created_on",
        "first" : {
            $first : "$value"
        },
        "second" : {
            $last : "$value"
        },
        "count" : {
            $sum : 1
        }
    }
}, {
    $project : {
        "_id" : 0,
        "value" : {
            $multiply : [ {
                $cond : [ {
                    $lte : [ "$count", 1 ]
                }, "$first", {
                    $subtract : [ "$first", "$second" ]
                } ]
            }, 0.25 ]
        },
        "created_on" : "$_id",
        "account" : {
            $literal : "C0"
        }
    }
} ]).forEach(function(doc) {
    doc.value = Math.abs(doc.value);
    db.time.insert(doc);
});

第二种解决方案基于实时场景。对于特定created_on时间,可能会有'n'个C1文档和'm'C2个具有不同值的文档,但我们只需要one表示特定'C0'时间差异的created_on文档。您需要一个额外的$group管道运算符,如下所示:

db.time.aggregate([ {
    $match : {
        "account" : {
            $in : [ "C1", "C2" ]
        }
    }
}, {
    $group : {
        "_id" : {
            "created_on" : "$created_on",
            "account" : "$account"
        },
        "created_on" : {
            $first : "$created_on"
        },
        "values" : {
            $sum : "$value"
        }
    }
}, {
    $group : {
        "_id" : "$created_on",
        "first" : {
            $first : "$values"
        },
        "second" : {
            $last : "$values"
        },
        "count" : {
            $sum : 1
        }
    }
}, {
    $project : {
        "_id" : 0,
        "value" : {
            $multiply : [ {
                $cond : [ {
                    $lte : [ "$count", 1 ]
                }, "$first", {
                    $subtract : [ "$first", "$second" ]
                } ]
            }, 0.25 ]
        },
        "created_on" : "$_id",
        "account" : {
            $literal : "C0"
        }
    }
} ]).forEach(function(doc) {
    doc.value = Math.abs(doc.value);
    db.time.insert(doc);
});