使用 MongoDB Aggregator Framework 格式化与 chartjs scatter 匹配的数据

Using MongoDB Aggregator Framework to format data that match with chartjs scatter

我是 MongoDB 中使用聚合器的新手,我想知道是否有一种方法可以在 MongoDB 级别格式化数据以准备使用 ChartJs scatter 绘图的结果。

所以我有一个时间序列数据集(我不确定这是存储时间序列数据的最佳方式,所以欢迎任何建议),如下所示:

{
    "dataset_id" : "850919c9-30e4-46f1-b962-e6b16cd30c60",
    "time_stamp" : 1600624542,
    "series" : [ 
        {
            "name" : "serie_0",
            "value" : 935.0
        }, 
        {
            "name" : "serie_1",
            "value" : 780.0
        }, 
        ...
        {
            "name" : "serie_n",
            "value" : <value_n>
        }, 
     ]
}

但是对于 ChartJS,我需要这样的格式:

[
    {
      label: '<series_0_name>',
      data: [
        {x: <timestamp>, y: <value>},
        ...
        {x: <timestamp>, y: <value>},
       ]
    },
    ...
    {
      label: '<series_n_name>',
      data: [
        {x: <timestamp>, y: <value>},
        ...
        {x: <timestamp>, y: <value>},
       ]
    },
]

此刻为了存档,我正在使用这个 python 代码(我正在使用 PyMongo):

def dataset_format(dataset_id, sample_size):
    match = {"$match": {"dataset_id": str(dataset_id)}}
    sample = {"$sample": {"size": sample_size}}
    unwind = {"$unwind": {"path": "$series"}}
    stages = [match, sample, unwind]

    pool = DB_POOL_COLLECTION.aggregate(stages)
    values = [
        (record["series"]["name"], record["time_stamp"], record["series"]["value"])
        for record in pool
    ]

    data = [
        {"label": d, "data": [{"x": v[1], "y": v[2]} for v in values if v[0] == d]}
        for d in set(name[0] for name in values)
    ]

    return data

但考虑到性能,我认为将此 python 格式化代码移动到 MongoDb 端会提高查询的性能。正如我之前所说,这个项目是从头开始的,所以我愿意接受有关我的数据库文档样式的建议,考虑到我需要良好的阅读性能,但我现在不关心写入性能。

我用这种方法做到了,我仍然不确定是否是最有效的方法,但现在的性能非常好

def dataset_info(dataset_id, sample_size):
    stages = [
        {"$match": {"dataset_id": str(dataset_id)}},
        {"$sample": {"size": sample_size}},
        {"$sort": {"time_stamp": 1}},
        {"$unwind": {"path": "$series"}},
        {
            "$project": {
                "label": "$series.name",
                "data": {
                    "x": {"$multiply": ["$time_stamp", 1000]},
                    "y": "$series.value",
                },
            }
        },
        {"$group": {"_id": "$label", "data": {"$push": "$data"}}},
        {
            "$project": {
                "_id": 0,
                "label": "$_id",
                "data": 1,
                "showLine": {"$toBool": 1},
                "fill": {"$toBool": 0},
            }
        },
        {"$sort": {"label": 1}},
    ]

    data = DB_POOL_COLLECTION.aggregate(stages)
    return list(data)

此 returns 数据结构已准备好用于 ChartJS,例如:

[
    {
      label: '<series_0_name>',
      showLine: true,
      fill: false,
      data: [
        {x: <timestamp in ms>, y: <value>},
        ...
        {x: <timestamp in ms>, y: <value>},
       ]
    },
    ...
    {
      label: '<series_n_name>',
      showLine: true,
      fill: false,
      data: [
        {x: <timestamp in ms>, y: <value>},
        ...
        {x: <timestamp in ms>, y: <value>},
       ]
    },
]