在MongoDB中搜索一段时间内的固定数量的文档

时间:2017-10-14 20:09:16

标签: database mongodb query-optimization

我们有一个包含大量文档的数据库,随着时间的推移它会越来越大。现在,查询时间不是问题,因为数据只有大约1年左右。但是,如果我们查询所有内容,查询得到的时间就越长。

我们的想法是获取每个第n个文档,文档越多,您就会留下一些数据,但是您仍然可以从数据中获得良好的图像。然而,这在Mongo中很难做到并且似乎根本不起作用,因为它仍然遍历所有文档。

有没有办法设置固定的查询时间,无论有多少文件,或至少减少它?只要我们从每个时间范围获取文档,我们是否会丢失整体数据并不重要。

1 个答案:

答案 0 :(得分:1)

我不确切知道您的数据是什么样的,但这是我的意思的一个例子。我们假设这是您存储在数据库中的数据。

/* 1 */
{
    "_id" : ObjectId("59e272e74d8a2fe38b86187d"),
    "name" : "data1",
    "date" : ISODate("2017-11-07T00:00:00.000Z"),
    "number" : 15
}

/* 2 */
{
    "_id" : ObjectId("59e272e74d8a2fe38b86187f"),
    "name" : "data2",
    "date" : ISODate("2017-11-06T00:00:00.000Z"),
    "number" : 19
}

/* 3 */
{
    "_id" : ObjectId("59e272e74d8a2fe38b861881"),
    "name" : "data3",
    "date" : ISODate("2017-10-06T00:00:00.000Z"),
    "number" : 20
}

/* 4 */
{
    "_id" : ObjectId("59e272e74d8a2fe38b861883"),
    "name" : "data4",
    "date" : ISODate("2017-10-05T00:00:00.000Z"),
    "number" : 65
}

我知道您想要在几个月甚至几年内比较一些值。所以你可以做以下

db.getCollection('test').aggregate([
{
    $match: {
        // query on the fields with index
        date: {$gte: ISODate("2017-10-05 00:00:00.000Z"), 
               $lte: ISODate("2017-11-07 00:00:00.000Z")}
    }
},
{
    // retrieve the month from each document
    $project: {
        _id: 1,
        name: 1,
        date: 1,
        number: 1,
        month: {$month: "$date"}
    }
},
{
    // group them by month and perform some accumulator operation
    $group: {
        _id: "$month",
        name: {$addToSet: "$name"},
        dateFrom: {$min: "$date"},
        dateTo: {$max: "$date"},
        number: {$sum: "$number"}
    }
}
])

我建议您保存预先汇总的数据,而不是每月搜索30个文档,例如您只需每月搜索1个。而且您只需要将完整数据聚合一次,如果您预先存储了预先汇总的结果,那么您只需要为即将进入的新数据运行预聚合。

这可能是您正在寻找的东西吗?

此外,如果你有索引,你查询它们的字段有索引,那么这也有帮助。否则,MongoDB必须扫描集合中的每个文档。