2010-05-31 3 views
252

Я играл вокруг хранения твитов внутри 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? Нужно ли обновлять мои документы, чтобы даты сохранялись в определенном формате?

+0

Вы не скажете, в каком поле вы хотите получить запрос? – shingara

+0

К сожалению, я хочу запросить created_at и найти все между двумя датами. – Tom

+0

Мне любопытно, почему бы не использовать временную метку, никаких преимуществ при использовании Date Obj? – Leo

ответ

395

Querying for a Date Range (Specific Month or Day) в MongoDB Cookbook имеет очень хорошее объяснение по этому вопросу, но ниже что-то я попробовал себя, и это, кажется, работает.

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

Выглядит интересно, но хранимая дата должна быть в определенном формате. Я только что сохранил то, что было предоставлено Twitter, нужно ли это изменить в другом формате? – Tom

+5

Возможно, вы сохранили временные метки как строки, поэтому я предполагаю, что MongoDB не поймет, что они на самом деле являются датами. Таким образом, выполнение запроса диапазона на них приведет к запросу в алфавитном диапазоне (например,«Jan Mon 01.01.2010» до «Jan Sun 01.01.1000»). Вероятно, было бы целесообразно форматировать все данные даты в формате MongoDB, который, я думаю, является просто простой датой JavaScript. – ponzao

+2

Я просто использовал это, чтобы преобразовать свои строки в современные объекты http://stackoverflow.com/questions/2900674/how-do-i-convert-a-property-in-mongodb-from-text-to-date-type – Tom

16

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

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

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

0

я пытался в этой модели, согласно моим требованиям я должен хранить дату, когда-либо объект создается позже я хочу, чтобы получить все записи (документы) между двумя датами в моем HTML файл я использовал следующие формат мм/дд/гггг

<!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> 

в моем файле ру (питон) я превратил его в «изо fomate» следующим способом

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

и сохраняются в моей коллекции dbmongo с «SelectedDate» в поле в моей коллекции

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

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

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

14

Чтобы уточнить. Важно знать, что:

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

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

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

Очень полезно. Я много помогал с проблемой. Спасибо –

2

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

+0

Потому что время не только происходит в моем местном часовом поясе. –

+1

Это становится кошмаром, когда вы начинаете конвертировать время в этот формат и из него. Если вы собираетесь сделать что-то подобное, по крайней мере, используйте возвращаемое значение из .getTime() из объекта даты JS. –

+1

Вот почему мы всегда храним данные в UTC – codewandler

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

Заменить collection с названием коллекции вы хотите выполнить запрос

0

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

{ 
    "_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 
    } 
] 
1

использование $ получить и $ лт найти между датой Дейты в 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"),$lt: new Date(tomorrowDate + "T23:59:59.999Z")}}) 
2

Python и pymongo

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

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 типов.