두 날짜 사이의 객체 찾기 MongoDB


406

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 사이의 모든 객체를 찾는 쿼리를 작성하는 방법은 무엇입니까? 날짜가 특정 형식으로 저장되도록 문서를 업데이트해야합니까?


어떤 필드를 쿼리하고 싶은지 말하지 않습니까?
shingara

죄송합니다. created_at을 쿼리하고 두 날짜 사이를 모두 찾고 싶습니다.
Tom

Date Obj를 사용하여 타임 스탬프를 사용하지 않는 이유가 무엇인지 궁금합니다.
Leo

4
@Leo 신기원이나 인간이 읽을 수있는 모든 것 이후 밀리 초에 걸쳐 Date 객체의 가장 큰 장점입니다. 이 경우 시작 범위를 설정하는 2010-04-29T00:00:00.000Z것이 동일한 날짜 / 시간을 밀리 초 단위로 계산하는 것보다 훨씬 쉽습니다. 시간대 변환도 매우 쉽게 할 수 있습니다. 또한 날짜는 이미 윤일, 윤초 및 일반적으로 자신이 처리하고 싶지 않은 다른 이상한 것들을 처리합니다.
Thunderforge

답변:


619

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" }

두 번째 예에서는 결과가 예상되지 않았지만 여전히 얻은 결과가있었습니다. 기본 문자열 비교가 완료 되었기 때문입니다.


3
흥미롭게 보이지만 저장된 날짜는 특정 형식이어야합니다. 방금 트위터가 제공 한 것을 저장하고 있는데 다른 형식으로 변경해야합니까?
Tom

7
타임 스탬프를 문자열로 저장했을 수도 있으므로 MongoDB는 실제로 날짜임을 알지 못합니다. 따라서 이들에 대한 범위 쿼리를 수행하면 알파벳 범위 쿼리가 발생합니다 (예 : "Jan Mon 01.01.2010"이 "Jan Sun 01.01.1000"이전). 모든 날짜 데이터를 MongoDB 형식으로 포맷하는 것이 합리적 일 것입니다. 일반적인 JavaScript 날짜라고 생각합니다.
ponzao 2016 년

2
방금 이것을 문자열을 날짜 객체로 변환하는 데 사용했습니다. stackoverflow.com/questions/2900674/…
Tom

좋아! 요리 책에 언급 된 범위 쿼리가 작동해야한다고 생각합니다. 이미 시도해 보셨습니까?
ponzao

그러나 일단 날짜를 저장하면 요리 책 예제가 예상대로 작동합니다.
Tom

35

명확히하기 위해. 알아야 할 중요한 사항은 다음과 같습니다.

  • 예, Javascript Date 객체를 전달해야합니다.
  • 예, ISODate 친화적이어야합니다.
  • 예,이 작업을 수행 한 경험에서 날짜를 ISO로 조작해야합니다.
  • 예, 날짜 작업은 일반적으로 지루한 과정이며 몽고도 예외는 아닙니다.

다음은 작동하는 코드 스 니펫입니다. 여기서 Mongo (여기서 mongoose 모듈을 사용하고 있고 날짜 속성이 myDate 매개 변수로 지정된 날짜보다 작은 행의 결과를 원합니다)를 처리하기 위해 약간의 날짜 조작을 수행합니다. 올바르게 :

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

1
명확성을 위해 플러스 하나. 백엔드에서 사용중인 모멘트가 여전히 toISOString () 함수를 유지합니다. 나는 질문에 시간을 더하고 빼기 위해 순간을 사용합니다.
VocoJax

17

MongoDB는 실제로 http://bsonspec.org/#/specification에 규정 된대로 날짜의 밀리 초를 int (64)로 저장합니다.

그러나 클라이언트 드라이버가 자체 로컬 시간대로 날짜 객체를 인스턴스화하므로 날짜를 검색 할 때 혼동 될 수 있습니다. mongo 콘솔의 JavaScript 드라이버가이를 수행합니다.

따라서 시간대에 관심이있는 경우 시간대를 되 찾을 때 예상되는 시간을 알아야합니다. 날짜 객체의 시간대에 관계없이 여전히 동일한 int (64)와 동일하기 때문에 쿼리에는 그렇게 중요하지 않습니다. 그러나 실제로 문자열이 아닌 실제 날짜 객체로 쿼리하고 드라이버가 그 일을하도록했습니다.


16

파이썬과 pymongo

pymongo컬렉션 에서를 사용하여 Python에서 두 날짜 사이의 객체 찾기 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.


작동하지 않습니다. 이 쿼리를 실행할 때마다 기본적으로 완전한 응답을 받고 필터링되지 않은 응답을 얻습니다
Abhay Bh

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

collection쿼리를 실행하려는 컬렉션 이름으로 교체


3
이것이 7 년 전에 제공된 대답에 무엇을 추가합니까?
Dan Dascalescu

1
@ DanDascalescu-아무 것도 추가하지 않았을 수도 있지만 여기에 관심사는 무엇입니까?
GSK

17
중복 된 답변은 사람들의 시간을 낭비합니다.
Dan Dascalescu

10

이 코드를 사용하여 $gteand를 사용하여 두 날짜 사이의 레코드를 찾으십시오 $lt.

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

8 년 전에 제공된 답변에 무엇이 추가됩니까?
Dan Dascalescu

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) { ... });

2

몽고에 날짜를 입력 할 때 날짜를 GMT 시간대로 변환하십시오. 그렇게하면 시간대 문제가 없습니다. 그런 다음 프리젠 테이션을 위해 데이터를 다시 가져올 때 Twitter / 시간대 필드에서 수학을 수행하십시오.


2

문자열을 YYYYMMDDHHMMSS 형식의 정수로 변환하지 않겠습니까? 그러면 시간이 증가 할 때마다 더 큰 정수가 생성되며 ISO 시간으로 변환하는 것을 걱정하지 않고 정수를 필터링 할 수 있습니다.


현지 시간대로 시간이 발생하는 것이 아니기 때문입니다.
Michael Cole

2
시간을 어디에서나 해당 형식으로 변환하기 시작하면 악몽이됩니다. 적어도 이와 같은 작업을 수행하려면 JS 날짜 객체의 .getTime () 반환 값을 사용하십시오.
nikk wong

1
그래서 우리는 항상 UTC로 데이터를 저장합니다
codewandler

2

mongodb에서 날짜 데이터 사이를 찾으 려면 $ gte$ lte 를 사용하십시오.

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")}})

1
귀하의 답변에 약간의 오타 $ gte $ get :)
Bob

1
매우 피곤한 상태로 대답해서 죄송합니다. 실수했습니다. 답변을 업데이트하는 데 도움을 주셔서 감사합니다. :
Bob

2

이것을 확인할 수도 있습니다. 이 방법을 사용하는 경우 구문 분석 기능을 사용하여 Mongo 데이터베이스에서 값을 가져 오십시오.

db.getCollection('user').find({
    createdOn: {
        $gt: ISODate("2020-01-01T00:00:00.000Z"),
        $lt: ISODate("2020-03-01T00:00:00.000Z")
    }
})

1
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`) ]
                        },
                    ]
                 }
              }
           }
        }
     }
])

1

당신은 또한 이것을 확인하거나 집계를 사용하는 대신 시도 할 수 있습니다

db.getCollection('user').find({
    createdOn: {
        $gt: ISODate("2020-01-01T00:00:00.000Z"),
        $lt: ISODate("2020-03-01T00:00:00.000Z")
    }
})

0

내 요구 사항에 따라이 모델에서 시도했습니다. 나중에 객체를 만들 때 날짜를 저장해야합니다 .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>

내 파이썬 (파이썬) 파일에서 다음과 같은 방법으로 "iso fomate"로 변환했습니다.

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

내 컬렉션의 필드로 "SelectedDate"를 사용하여 dbmongo 컬렉션에 저장되었습니다.

다음 쿼리에서 사용 한 2 일 사이의 데이터 또는 문서를 검색합니다.

db.collection.find( "SelectedDate": {'$gte': SelectedDate1,'$lt': SelectedDate2}})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.