在where子句中计算

时间:2017-05-10 09:58:37

标签: mongodb mongoose

给出以下架构

var schema = new Schema({
    activeDuration:         {type: Number, required: true},
}, {
    timestamps: true
});

activeDuration是以天为单位的时间。如何创建等于SELECT FROM schema WHERE (UNIX_TIMESTAMP(createdAt) + (activeDuration * 24 * 60 * 60)) < CURRENT_TIMESTAMP;

的查询

所以我应该收到所有不是&#34;活跃&#34;再次(对象插入数据库的时间+给定的持续时间小于当前时间)。

2 个答案:

答案 0 :(得分:1)

您需要使用 $redact 运算符的汇总管道,因为它允许您使用 $cond 运算符并使用特殊操作 $$KEEP 来“保留”逻辑条件为真的文档或 $$PRUNE 以“删除”文档条件错误的地方。

此操作类似于具有 $project 管道,该管道选择集合中的字段并创建一个新字段,其中包含逻辑条件查询的结果,然后是后续的 $match ,但 $redact 执行单个管道阶段中的所有计算,效率更高。

至于逻辑条件,有Date Aggregate Operators个和Arithmetic个来帮助计算。

考虑以下示例管道:

Model.aggregate([
    {
        "$redact": {
            "$cond": [
                {
                    "$lt": [
                        {
                            "$add": [
                                "$createdAt",
                                { "$multiply": ["$activeDuration", 24 * 60 * 60]}
                            ]
                        },
                        new Date()
                    ]
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
], (err, data) => {
    if (err) throw err;
    console.log(data);
})

如果使用 find() 方法,则可以将 $where 应用为

Model.find({ "$where": "(this.createdAt.valueOf() + (this.activeDuration * 24 * 60 * 60)) < +new Date()" })
     .exec((err, data) => {
        if (err) throw err;
        console.log(data);          
     })

请注意使用 $where 时的性能成本,因为操作员调用JavaScript引擎来评估每个文档上的JavaScript代码并检查每个文档的条件。如果可以的话,建议与索引查询结合使用,以便查询可以更快。

答案 1 :(得分:1)

正如我的评论中所述,我在游戏结束时添加了一个endsAt字段,其中包含Date()。查询非常简单:

    var query = Game.find({"endsAt": {"$lt": new Date()}});