Mongoose如何在日期范围内查询并提取每天的最高价值?

时间:2014-02-12 21:16:16

标签: javascript node.js mongodb mongoose aggregation-framework

如何使用mongoose / mongodb设计查询以在日期范围内搜索并提取该范围内每天的最高价格值?现在,我知道如何执行此操作的唯一方法是在日期范围内执行查询,然后处理结果以获取每天的最高价格。但这似乎是一个常见的需求,所以我想知道是否可以在查询中完成所有操作:

这是我的模型,它提供了一些可以在查询中使用的不同内容。 date属性是Date类型,day属性是字符串类型。 day属性采用此格式day: "02/11/2014"price属性是Number数据类型,格式为:price: 114.61

// Price Schema
var PriceSchema = new Schema({
    full_date: {
        type: String,
        required: true,
        unique: true,
        trim: true
    },
    day: {
        type: String,
        required: true,
        trim: true
    },
    price: {
        type: Number,
        required: true,
        trim: true
    },
    date: {
        type: Date,
        unique: true,
        required: true
    }
});

以下是日期范围内的查询,但是我可以执行类似于每个日期返回最高价格的内容吗?

Price.find({ date: { $lt: end, $gt: start }}, function(err, prices) {
            if (err) {
                console.log(err);
            } else {
                res.jsonp(poolprices);
            }
        });

1 个答案:

答案 0 :(得分:5)

您可能希望使用aggregation pipeline

Price.aggregate([
    // Match the date range
    { "$match": { "date": { "$lt": end, "$gt": start} } },

    // Change document with date to a value just for the day
    { "$project":{ 
        "date": {
           "year": { "$year": "$date"}, 
           "month": { "$month": "$date" }, 
           "day": { "$dayOfMonth": "$date"}
        },
        "price": 1
    }},

    // Sort everything (descending so highest price per day is on top)
    { "$sort": { "date.year": -1, "date.month": -1, "date.day": -1, "price": -1 }},

    // Group per day (now as a nice string), and keep the first price (highest)
    { "$group": { 
        "_id": {
            "$concat": [{ "$substr": ["$date.year", 0, 4] },
            "-",
           { "$substr": ["$date.month", 0, 2]},
            "-", 
           { "$substr": ["$date.day", 0, 2]}]
        },
        "price": { "$first": "$price"}
    }},

    // Make field names nicer
    { "$project": { "_id":0, "day": "$_id", "price": 1 } }

],
function(err,result) {
    //process here
})

因此,结果在您的范围内每天只有1个价格,并且无需以编程方式循环结果。

这是一个很好的小操作,它使用Date Operators来分解日期字段,然后使用$substr$concat来为结果返回更好的值。考虑到您现在知道在这里可以做什么,您也可以重新考虑模式中的一些字段。