MongoDB Project / Aggregate获取所有子文档的最新数组条目

时间:2016-04-08 12:05:57

标签: mongodb mongodb-query aggregation-framework

我使用MongoDB来存储带有间隙的时间序列数据。每个文档属于一个项目,并保存多个度量点的更改。 每个度量点都有一个id,我在下面的例子中使用了以下id方案some-id-XXX

应用程序仅写入对特定子文档的更改。因此,APP加载的系列中可能存在间隙,整个文档会对其进行检查以进行更改,并更新已更改的子文档(例如"some-id-1")。

{
    "_id": "XXX-DAY_OF_YEAR",
    "date": null /* A date used for the TTL index */,
    "series" : {
        "some-id-1" : [
            {
                "ts" : 1457959837,
                "value" : 385,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1457959837,
                "value" : 385,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458286255,
                "value" : 380,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458346606,
                "value" : 375,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458381111,
                "value" : 368,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458381461,
                "value" : 365,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458606338,
                "value" : 385,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458606338,
                "expired": true
            }
        ],
        "some-id-2" : [
            {
                "ts" : 1439802083,
                "value" : 430,
                "meta" : "some meta info …"
            }
        ],
        "some-id-42" : [
            {
                "ts" : 1457545167,
                "value" : 518,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458483441,
                "value" : 1034,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458518979,
                "value" : 518,
                "meta" : "some meta info …"
            }
        ],
        "some-id-1337" : [
            {
                "ts" : 1458017854,
                "value" : 361,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458050773,
                "value" : 384,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458115173,
                "value" : 383,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458143968,
                "value" : 382,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458176011,
                "value" : 381,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458212600,
                "value" : 384,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458245285,
                "value" : 383,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458277108,
                "value" : 382,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458309875,
                "value" : 379,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458338258,
                "value" : 378,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458374471,
                "value" : 374,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458405856,
                "value" : 364,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458435330,
                "value" : 363,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458471185,
                "value" : 362,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458500103,
                "value" : 361,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458535837,
                "value" : 360,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458568805,
                "value" : 364,
                "meta" : "some meta info …"
            },
            {
                "ts" : 1458633188,
                "value" : 384,
                "meta" : "some meta info …"
            }
        ]
    }
}

此approcach的问题是加载整个文档所产生的流量,这是检查更改或间隙所需的。

如果我只能检索最近的值(数组中的最后一个值),流量就会被削减。

{
    "series" : {
        "some-id-1" : [
            {
                "ts" : 1458606338,
                "expired": true
            }
        ],
        "some-id-2" : [
            {
                "ts" : 1439802083,
                "value" : 430,
                "meta" : "some meta info …"
            }
        ],
        "some-id-42" : [
            {
                "ts" : 1458518979,
                "value" : 518,
                "meta" : "some meta info …"
            }
        ],
        "some-id-1337" : [
            {
                "ts" : 1458633188,
                "value" : 384,
                "meta" : "some meta info …"
            }
        ]
    }
}

只要我知道ID,我就可以使用投影来检索最近的最新条目。

db.Series.find( 
{ "series.some-id-42" : { $exists: true } },
{ "series.some-id-42.$": -1}
)   

但由于更改可能包含间隙,因此我不知道目标系列文档中出现的所有ID。

是否有可能使用聚合框架或一些聪明的投影来存档?

我唯一的想法是以更紧凑的形式存储最近的值,并仅投影{last_recent: 1}

{
    "recent": {
        "some-id-1" : 0,
        "some-id-2" : 430,
        "some-id-42" : 518,
        "some-id-1337" : 384
    }
    "series" : { /* … */ }
}

但我希望有一个更优雅的解决方案来解决这个问题。

1 个答案:

答案 0 :(得分:0)

核心问题是您将数据存储在字段名称中,即ID。

架构应该是:

{
    "series": [
        {
            "id": 1,
            "content": [
                {
                    "ts": 1458606338,
                    "expired": true
                }
            ]
        },
        {
            "id": 2,
            "content": [
                {
                    "ts": 1439802083,
                    "value": 430,
                    "meta": "some meta info …"
                }
            ]
        },
        {
            "id": 42,
            "content": [
                {
                    "ts": 1458518979,
                    "value": 518,
                    "meta": "some meta info …"
                }
            ]
        },
        {
            "id": 1337,
            "content": [
                {
                    "ts": 1458633188,
                    "value": 384,
                    "meta": "some meta info …"
                }
            ]
        }
    ]
}