Найти объекты между двумя датами MongoDB

Я занимаюсь хранением твитов внутри mongodb, каждый объект выглядит следующим образом:

{
"_id" : ObjectId("4c02c58de500fe1be1000005"),
"contributors" : null,
"text" : "Hello world",
"user" : {
    "following" : null,
    "followers_count" : 5,
    "utc_offset" : null,
    "location" : "",
    "profile_text_color" : "000000",
    "friends_count" : 11,
    "profile_link_color" : "0000ff",
    "verified" : false,
    "protected" : false,
    "url" : null,
    "contributors_enabled" : false,
    "created_at" : "Sun May 30 18:47:06 +0000 2010",
    "geo_enabled" : false,
    "profile_sidebar_border_color" : "87bc44",
    "statuses_count" : 13,
    "favourites_count" : 0,
    "description" : "",
    "notifications" : null,
    "profile_background_tile" : false,
    "lang" : "en",
    "id" : 149978111,
    "time_zone" : null,
    "profile_sidebar_fill_color" : "e0ff92"
},
"geo" : null,
"coordinates" : null,
"in_reply_to_user_id" : 149183152,
"place" : null,
"created_at" : "Sun May 30 20:07:35 +0000 2010",
"source" : "web",
"in_reply_to_status_id" : {
    "floatApprox" : 15061797850
},
"truncated" : false,
"favorited" : false,
"id" : {
    "floatApprox" : 15061838001
}

Как мне написать запрос, который проверяет created_at и находит все объекты между 18:47 и 19:00? Нужно ли обновлять мои документы, чтобы даты сохранялись в определенном формате?

Ответ 1

Запрос для диапазона дат (определенный месяц или день) в Cookbook в MongoDB имеет очень хорошее объяснение по этому вопросу, но ниже это то, что я опробовал сам и, похоже, работает.

items.save({
    name: "example",
    created_at: ISODate("2010-04-30T00:00:00.000Z")
})
items.find({
    created_at: {
        $gte: ISODate("2010-04-29T00:00:00.000Z"),
        $lt: ISODate("2010-05-01T00:00:00.000Z")
    }
})
=> { "_id" : ObjectId("4c0791e2b9ec877893f3363b"), "name" : "example", "created_at" : "Sun May 30 2010 00:00:00 GMT+0300 (EEST)" }

Основываясь на моих экспериментах, вам нужно будет сериализовать свои даты в формате, поддерживаемом MongoDB, потому что следующее дало нежелательные результаты поиска.

items.save({
    name: "example",
    created_at: "Sun May 30 18.49:00 +0000 2010"
})
items.find({
    created_at: {
        $gte:"Mon May 30 18:47:00 +0000 2015",
        $lt: "Sun May 30 20:40:36 +0000 2010"
    }
})
=> { "_id" : ObjectId("4c079123b9ec877893f33638"), "name" : "example", "created_at" : "Sun May 30 18.49:00 +0000 2010" }

Во втором примере результаты не ожидались, но все равно один получил. Это связано с тем, что выполняется базовое сравнение строк.

Ответ 2

Прояснить. Важно знать, что:

  • Да, вы должны передать объект Date Javascript.
  • Да, он должен быть дружелюбным к ISODate
  • Да, по моему опыту, чтобы это работало, вам нужно манипулировать датой ISO
  • Да, работа с датами, как правило, всегда является утомительным процессом, а mongo не является исключением.

Вот рабочий фрагмент кода, в котором мы немного обрабатываем дату, чтобы обеспечить Mongo (здесь я использую модуль mongoose и хочу получить результаты для строк, атрибут даты которых меньше (до) даты, указанной как параметр myDate ) может корректно справиться с этим:

var inputDate = new Date(myDate.toISOString());
MyModel.find({
    'date': { $lte: inputDate }
})

Ответ 3

MongoDB фактически хранит миллины даты как int (64), как предписано http://bsonspec.org/#/specification

Однако при получении дат, когда клиентский драйвер будет создавать экземпляр объекта даты с его собственной локальной часовым поясом, он может стать довольно запутанным. Драйвер JavaScript в консоли mongo, безусловно, сделает это.

Итак, если вы заботитесь о своих часовых поясах, убедитесь, что знаете, что это должно быть, когда вы его получите. Это не должно иметь большого значения для запросов, поскольку оно все равно будет соответствовать одному и тому же int (64), независимо от того, в какой временной зоне находится объект даты (надеюсь). Но я бы определенно делал запросы с фактическими объектами даты (а не строками) и позволял водителю делать свое дело.

Ответ 4

db.collection.find({"createdDate":{$gte:new ISODate("2017-04-14T23:59:59Z"),$lte:new ISODate("2017-04-15T23:59:59Z")}}).count();

Замените collection именем коллекции, которую вы хотите выполнить.

Ответ 5

Python и pymongo

Поиск объектов между двумя датами в Python с pymongo в коллекции posts (на основе учебника):

from_date = datetime.datetime(2010, 12, 31, 12, 30, 30, 125000)
to_date = datetime.datetime(2011, 12, 31, 12, 30, 30, 125000)

for post in posts.find({"date": {"$gte": from_date, "$lt": to_date}}):
    print(post)

Где {"$gte": from_date, "$lt": to_date} указывает диапазон в терминах типов datetime.datetime.

Ответ 6

Используйте этот код, чтобы найти запись между двумя датами, используя $gte и $lt:

db.CollectionName.find({"whenCreated": {
    '$gte': ISODate("2018-03-06T13:10:40.294Z"),
    '$lt': ISODate("2018-05-06T13:10:40.294Z")
}});

Ответ 7

Использование с Moment.js и операторами запросов сравнения

  var today = moment().startOf('day');
  // "2018-12-05T00:00:00.00
  var tomorrow = moment(today).endOf('day');
  // ("2018-12-05T23:59:59.999

  Example.find(
  {
    // find in today
    created: { '$gte': today, '$lte': tomorrow }
    // Or greater than 5 days
    // created: { $lt: moment().add(-5, 'days') },
  }), function (err, docs) { ... });

Ответ 8

Преобразуйте свои даты в часовой пояс GMT, когда вы набиваете их в Mongo. Таким образом, никогда не возникает проблема с часовым поясом. Затем просто сделайте математику в поле твиттера/часового пояса, когда вы вытащите данные для презентации.

Ответ 9

Почему бы не преобразовать строку в целое число формы YYYYMMDDHHMMSS? Каждое добавление времени создавало бы большее целое число, и вы могли бы фильтровать целые числа, а не беспокоиться о преобразовании в время ISO.

Ответ 10

используйте $ gte и $ lte для поиска данных даты в mongodb

var tomorrowDate = moment(new Date()).add(1, 'days').format("YYYY-MM-DD");
db.collection.find({"plannedDeliveryDate":{ $gte: new Date(tomorrowDate +"T00:00:00.000Z"),$lte: new Date(tomorrowDate + "T23:59:59.999Z")}})

Ответ 11

Я попытался в этой модели в соответствии с моими требованиями. Мне нужно хранить дату, когда когда-либо создается объект. Я хочу получить все записи (документы) между двумя датами  в моем html файле Я использовал следующий формат: mm/dd/yyyy

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>

    <script>
//jquery
    $(document).ready(function(){  
    $("#select_date").click(function() { 
    $.ajax({
    type: "post",
    url: "xxx", 
    datatype: "html",
    data: $("#period").serialize(),  
    success: function(data){
    alert(data);
    } ,//success

    }); //event triggered

    });//ajax
    });//jquery  
    </script>

    <title></title>
</head>

<body>
    <form id="period" name='period'>
        from <input id="selecteddate" name="selecteddate1" type="text"> to 
        <input id="select_date" type="button" value="selected">
    </form>
</body>
</html>

в моем файле py (python) я преобразовал его в "iso fomate" следующим образом

date_str1   = request.POST["SelectedDate1"] 
SelectedDate1   = datetime.datetime.strptime(date_str1, '%m/%d/%Y').isoformat()

и сохранен в моей коллекции dbmongo с полем "SelectedDate" в моей коллекции

для получения данных или документов между двумя датами, которые я использовал в следующем запросе

db.collection.find( "SelectedDate": {'$gte': SelectedDate1,'$lt': SelectedDate2}})

Ответ 12

Имя коллекции: заказы

{
    "_id" : ObjectId("590070186bcc993d9c316ac1"),
    "updatedAt" : ISODate("2017-04-26T10:07:04.344Z"),
    "createdAt" : ISODate("2017-04-26T10:02:00.489Z"),
    "fullName" : "test last",
    "imgLength" : 5,
    "firstName" : "test",
    "lastName" : "last",
    "address" : "test",
    "state" : "test",
    "city" : "test",
    "zipCode" : 123456,
    "user" : ObjectId("58f760e771fd1737d1f9b4e5"),
    "orderId" : "PHA454494125243881",
    "status" : "Pending",
    "imgUrls" : [ ],
    "__v" : 0
}
{
    "_id" : ObjectId("590071622e6d953e411dec3f"),
    "updatedAt" : ISODate("2017-04-20T10:37:46.569Z"),
    "createdAt" : ISODate("2017-04-20T10:07:30.572Z"),
    "fullName" : "test last",
    "imgLength" : 5,
    "firstName" : "test",
    "lastName" : "last",
    "address" : "test",
    "state" : "test",
    "city" : "test",
    "zipCode" : 123456,
    "user" : ObjectId("58f760e771fd1737d1f9b4e5"),
    "orderId" : "PHA300991061399836",
    "status" : "Pending",
    "imgUrls" : [ ],
    "__v" : 0
}
{
    "_id" : ObjectId("590071902e6d953e411dec40"),
    "updatedAt" : ISODate("2017-04-15T10:08:16.111Z"),
    "createdAt" : ISODate("2017-04-15T10:08:16.111Z"),
    "fullName" : "test last",
    "imgLength" : 5,
    "firstName" : "test",
    "lastName" : "last",
    "address" : "test",
    "state" : "test",
    "city" : "test",
    "zipCode" : 123456,
    "user" : ObjectId("58f760e771fd1737d1f9b4e5"),
    "orderId" : "PHA876174070036339",
    "status" : "Pending",
    "imgUrls" : [ ],
    "__v" : 0
}

Если вы хотите получить данные между двумя датами, вы можете выполнить следующий запрос:

db.orders.find({
             createdAt:{
                     $gt:ISODate("2017-04-10T10:08:16.111Z"),
                     $lt:ISODate("2017-05-25T10:08:16.111Z")}
              }).pretty();

ваш результат будет следующим:

[

    {
        "_id" : ObjectId("590071622e6d953e411dec3f"),
        "updatedAt" : ISODate("2017-04-20T10:37:46.569Z"),
        "createdAt" : ISODate("2017-04-20T10:07:30.572Z"),
        "fullName" : "test last",
        "imgLength" : 5,
        "firstName" : "test",
        "lastName" : "last",
        "address" : "test",
        "state" : "test",
        "city" : "test",
        "zipCode" : 123456,
        "user" : ObjectId("58f760e771fd1737d1f9b4e5"),
        "orderId" : "PHA300991061399836",
        "status" : "Pending",
        "imgUrls" : [ ],
        "__v" : 0
    }
    {
        "_id" : ObjectId("590071902e6d953e411dec40"),
        "updatedAt" : ISODate("2017-04-15T10:08:16.111Z"),
        "createdAt" : ISODate("2017-04-15T10:08:16.111Z"),
        "fullName" : "test last",
        "imgLength" : 5,
        "firstName" : "test",
        "lastName" : "last",
        "address" : "test",
        "state" : "test",
        "city" : "test",
        "zipCode" : 123456,
        "user" : ObjectId("58f760e771fd1737d1f9b4e5"),
        "orderId" : "PHA876174070036339",
        "status" : "Pending",
        "imgUrls" : [ ],
        "__v" : 0
    }
]

Ответ 13

mongoose.model('ModelName').aggregate([
    {
        $match: {
            userId: mongoose.Types.ObjectId(userId)
        }
    },
    {
        $project: {
            dataList: {
              $filter: {
                 input: "$dataList",
                 as: "item",
                 cond: { 
                    $and: [
                        {
                            $gte: [ "$$item.dateTime", new Date('2017-01-01T00:00:00.000Z') ]
                        },
                        {
                            $lte: [ "$$item.dateTime", new Date('2019-12-01T00:00:00.000Z') ]
                        },
                    ]
                 }
              }
           }
        }
     }
])