比较mongo find方法中的2个日期

时间:2015-07-07 15:10:32

标签: mongodb mongodb-query

我有包含last_active日期和创建日期的mongo文档。我想搜索last_active的不等于创建的的所有文档,但我不知道如何编写查询。

在MySQL中,我会这样写:

WHERE DATE_FORMAT(created, '%Y-%m-%d') != DATE_FORMAT(last_active, '%Y-%m-%d')

4 个答案:

答案 0 :(得分:3)

对于MongoDB 3.6及更高版本:

$expr 运算符允许在查询语言中使用聚合表达式,因此您可以利用 $dateToString 运算符进行转换日期字段:

db.test.find({ 
    "$expr": { 
        "$ne": [ 
             { "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } }, 
             { "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
        ] 
    } 
})

或使用聚合框架与 $match 管道

db.test.aggregate([
    { "$match": { 
        "$expr": { 
            "$ne": [ 
                { "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } }, 
                { "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
            ] 
        } 
    } }
])

对于MongoDB 3.0 +:

您还可以将聚合框架与 $redact 管道运算符一起使用,该运算符允许您使用 $cond 运算符处理逻辑条件,使用特殊操作 $$KEEP 来"保持"逻辑条件为真的文档或 $$PRUNE 到"删除"条件错误的文件。

考虑运行以下聚合操作,该操作演示了上述概念:

db.test.aggregate([
    {
        "$redact": {
            "$cond": [
                { 
                    "$ne": [ 
                        { "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } }, 
                        { "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

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

db.test.aggregate([
    {
        "$project": { 
            "created": 1, 
            "last_active": 1,
            "sameDay": { 
                "$cond": [ 
                    { 
                        "$eq": [ 
                            {"$substr" : ["$last_active",0, 10]}, 
                            {"$substr" : ["$created",0, 10]}
                        ] 
                    }, true, false 
                ]
            } 
        } 
    },
    { "$match": { "sameDay": false } }
])

0R

db.test.aggregate([
    {
        "$project": { 
            "created": 1, 
            "last_active": 1,
            "sameDay": { 
                "$cond": [ 
                    { 
                        "$eq": [ 
                            { "$dateToString": { "format": "%Y-%m-%d", "date": "$created" } }, 
                            { "$dateToString": { "format": "%Y-%m-%d", "date": "$last_active" } }
                        ] 
                    }, true, false 
                ]
            } 
        } 
    },
    { "$match": { "sameDay": false } }
])

另一种方法是在 find() 方法中使用 $where 运算符,但请注意,由于使用< strong> $where 单独需要进行表扫描,并且数据库为集合中的每个文档执行JavaScript表达式或函数,因此如果可以,那么当您使用表达式查询时,查询性能也会提高标准的MongoDB运算符(例如, $gt $in ):

db.test.find({ 
   "$where": function() { 
       return this.created.getDate() !== this.last_active.getDate() 
   } 
});

或更紧凑:

db.test.find({ "$where": "this.created.getDate() !== this.last_active.getDate()" });

输入:

/* 0 */
{
    "_id" : 1,
    "created" : ISODate("2014-12-19T06:01:17.171Z"),
    "last_active" : ISODate("2014-12-21T15:38:13.842Z")
}

/* 1 */
{
    "_id" : 2,
    "created" : ISODate("2015-07-06T12:17:32.084Z"),
    "last_active" : ISODate("2015-07-06T18:07:08.145Z")
}

/* 2 */
{
    "_id" : 3,
    "created" : ISODate("2015-07-06T06:01:17.171Z"),
    "last_active" : ISODate("2015-07-07T10:04:30.921Z")
}

/* 3 */
{
    "_id" : 4,
    "created" : ISODate("2015-07-06T06:01:17.171Z"),
    "last_active" : ISODate("2015-07-06T09:47:44.186Z")
}

/* 4 */
{
    "_id" : 5,
    "created" : ISODate("2013-12-19T06:01:17.171Z"),
    "last_active" : ISODate("2014-01-20T13:21:37.427Z")
}

聚合返回:

/* 0 */
{
    "result" : [ 
        {
            "_id" : 1,
            "created" : ISODate("2014-12-19T06:01:17.171Z"),
            "last_active" : ISODate("2014-12-21T15:38:13.842Z"),
            "sameDay" : false
        }, 
        {
            "_id" : 3,
            "created" : ISODate("2015-07-06T06:01:17.171Z"),
            "last_active" : ISODate("2015-07-07T10:04:30.921Z"),
            "sameDay" : false
        }, 
        {
            "_id" : 5,
            "created" : ISODate("2013-12-19T06:01:17.171Z"),
            "last_active" : ISODate("2014-01-20T13:21:37.427Z"),
            "sameDay" : false
        }
    ],
    "ok" : 1
}

答案 1 :(得分:0)

在mongo聚合中使用$cond找出created != last_active检查以下聚合:

db.collectionName.aggregate([
{
    "$project": {
        "check": {
            "$cond": {
                "if": {
                    "$ne": [
                        "$created",
                        "$last_active"
                    ]
                },
                "then": 1,
                "else": 0
            }
        },
        "all": "$$ROOT"
    }
},
{
    "$match": {
        "check": 1
    }
},
{
    "$project": {
        "_id": 0,
        "all": 1
    }
}
 ]).pretty()

答案 2 :(得分:0)

执行此操作的一种方法是使用$ http://docs.mongodb.org/manual/reference/operator/query/where/ 或者您可以使用聚合查询。像这样的东西(改进以添加你需要检索的字段):

db.dates.aggregate({$project: { created: 1, last_active: 1, are_diff: {$ne: ["$created", "$last_active"]}}}, {$match: {are_diff: true}})

答案 3 :(得分:0)

您可以在查询中使用某个功能:

db.mycollection.find({
  $where: function() {
    return this.created.getDate() !== this.last_active.getDate();
  }
})