52

我正在使用 mongodb,并以这种方式将日期时间存储在我的数据库中

对于日期“17-11-2011 18:00”,我存储:

date = datetime.datetime(2011, 11, 17, 18, 0)
db.mydatabase.mycollection.insert({"date" : date})

我想做这样的请求

month = 11
db.mydatabase.mycollection.find({"date.month" : month})

或者

day = 17
db.mydatabase.mycollection.find({"date.day" : day})

有谁知道怎么做这个查询?

4

7 回答 7

59

日期以其时间戳格式存储。如果您想要属于特定月份的所有内容,请查询月份的开始和结束。

var start = new Date(2010, 11, 1);
var end = new Date(2010, 11, 30);

db.posts.find({created_on: {$gte: start, $lt: end}});
//taken from http://cookbook.mongodb.org/patterns/date_range/
于 2011-11-15T13:09:24.620 回答
32

您不能按日期或月份等日期组件直接查询 mongodb 集合。但它可能通过使用特殊的$where javascript 表达式

db.mydatabase.mycollection.find({$where : function() { return this.date.getMonth() == 11} })

或者干脆

db.mydatabase.mycollection.find({$where : 'return this.date.getMonth() == 11'})

(但我更喜欢第一个)

查看以下 shell 命令以获取日期部分

>date = ISODate("2011-09-25T10:12:34Z")
> date.getYear()
111
> date.getMonth()
8
> date.getdate()
25

编辑:

仅当您别无选择时才使用 $where。它伴随着性能问题。请查看@kamaradclimber 和@dcrosta 的以下评论。我会让这篇文章打开,以便其他人了解它的事实。

并查看链接$where Clauses and Functions in Queries了解更多信息

于 2011-11-15T13:16:16.610 回答
13

由于您需要查询月份,如何将月份存储在它自己的属性中?不如 优雅$where,但可能表现更好,因为它可以被索引。

于 2011-11-16T05:38:25.400 回答
11

如果要搜索属于特定月份的文档,请确保像这样查询:

// Anything greater than this month and less than the next month
db.posts.find({created_on: {$gte: new Date(2015, 6, 1), $lt: new Date(2015, 7, 1)}});

尽可能避免像下面这样查询。

// This may not find document with date as the last date of the month
db.posts.find({created_on: {$gte: new Date(2015, 6, 1), $lt: new Date(2015, 6, 30)}});

// don't do this too
db.posts.find({created_on: {$gte: new Date(2015, 6, 1), $lte: new Date(2015, 6, 30)}});
于 2015-06-12T04:55:01.017 回答
8

使用$expr允许在查询语言中使用聚合表达式的运算符。这将使您能够在查询中使用日期聚合运算符,如下所示:

month = 11
db.mydatabase.mycollection.find({ 
    "$expr": { 
        "$eq": [ { "$month": "$date" }, month ] 
    } 
})

或者

day = 17
db.mydatabase.mycollection.find({ 
    "$expr": { 
        "$eq": [ { "$dayOfMonth": "$date" }, day ] 
    } 
})

您还可以使用接受管道的aggregate()函数运行聚合操作:$redact

month = 11
db.mydatabase.mycollection.aggregate([
    {
        "$redact": {
            "$cond": [
                { "$eq": [ { "$month": "$date" }, month ] },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

对于另一个请求

day = 17
db.mydatabase.mycollection.aggregate([
    {
        "$redact": {
            "$cond": [
                { "$eq": [ { "$dayOfMonth": "$date" }, day ] },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

使用或

month = 11
day = 17
db.mydatabase.mycollection.aggregate([
    {
        "$redact": {
            "$cond": [
                { 
                    "$or": [ 
                        { "$eq": [ { "$month": "$date" }, month ] },
                        { "$eq": [ { "$dayOfMonth": "$date" }, day ] }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

使用 AND

var month = 11,
    day = 17;
db.collection.aggregate([
    {
        "$redact": {
            "$cond": [
                { 
                    "$and": [ 
                        { "$eq": [ { "$month": "$createdAt" }, month ] },
                        { "$eq": [ { "$dayOfMonth": "$createdAt" }, day ] }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

$redact运算符合并了$project和管道的功能,并将使用该变量$match返回与条件匹配的所有文档,并从管道中丢弃那些使用该变量$$KEEP不匹配的文档。$$PRUNE

于 2017-02-20T12:06:41.060 回答
5

您可以通过日期聚合运算符查找按月、日、年等记录的日期,例如$dayOfYear、$dayOfWeek、$month、$year等。

例如,如果您想要在 2016 年 4 月创建的所有订单,您可以使用以下查询。

db.getCollection('orders').aggregate(
   [
     {
       $project:
         {
           doc: "$$ROOT",
           year: { $year: "$created" },
           month: { $month: "$created" },
           day: { $dayOfMonth: "$created" }
         }
     },
     { $match : { "month" : 4, "year": 2016 } }
   ]
)

这里创建的是文档中的日期类型字段,$$ROOT 我们用来将所有其他字段传递给下一阶段的项目,并为我们提供文档的所有详细信息。

您可以根据需要优化上述查询,这只是举例。要了解有关日期聚合运算符的更多信息,请访问链接

于 2017-02-15T07:25:59.630 回答
-1

您可以使用MongoDB_DataObject包装器执行如下查询:

$model = new MongoDB_DataObject('orders');

$model->whereAdd('MONTH(created) = 4 AND YEAR(created) = 2016');

$model->find();

while ($model->fetch()) {
    var_dump($model);
}

或者,类似地,使用直接查询字符串:

$model = new MongoDB_DataObject();

$model->query('SELECT * FROM orders WHERE MONTH(created) = 4 AND YEAR(created) = 2016');

while ($model->fetch()) {
    var_dump($model);
}
于 2017-02-16T04:49:00.987 回答