날짜별로 MongoDB ObjectId를 쿼리 할 수 ​​있습니까?


답변:


224

타임 스탬프를 ObjectId에 넣는 것은 ObjectId에 포함 된 날짜를 기반으로하는 쿼리를 매우 자세하게 다룹니다.

JavaScript 코드에서 간단히 :

/* This function returns an ObjectId embedded with a given datetime */
/* Accepts both Date object and string input */

function objectIdWithTimestamp(timestamp) {
    /* Convert string date to Date object (otherwise assume timestamp is a date) */
    if (typeof(timestamp) == 'string') {
        timestamp = new Date(timestamp);
    }

    /* Convert date object to hex seconds since Unix epoch */
    var hexSeconds = Math.floor(timestamp/1000).toString(16);

    /* Create an ObjectId with that hex timestamp */
    var constructedObjectId = ObjectId(hexSeconds + "0000000000000000");

    return constructedObjectId
}


/* Find all documents created after midnight on May 25th, 1980 */
db.mycollection.find({ _id: { $gt: objectIdWithTimestamp('1980/05/25') } });

29
매우 편리합니다. 참고로,이 기능을 ~/.mongorc.js파일에 저장 하여 mongo쉘이 시작될 때 사용할 수 있습니다 .
Stennie

1
ReferenceError : ObjectId가 정의되지 않았습니다. 어떻게 고치나요?
peter

3
mongodbnative와 함께 nodejs를 사용하고 있습니다. var ObjectId = require ( 'mongodb'). ObjectID;를 포함하여 "정의되지 않은 오류"를 수정했습니다.
peter

1
변경 : 당신이 Mongoskin를 사용하는 경우 나처럼 ObjectId(hexSeconds + "0000000000000000");db.ObjectID.createFromHexString(hexSeconds + "0000000000000000");
앤더스 Östman

2
또는, 몽구스의 대체 ObjectId()와 함께 : require('mongoose').Types.ObjectId()- 여기서 require('mongoose')당신의 초기화 / 구성 몽구스 인스턴스입니다.
toblerpwn 2018 년

34

Node.js의 mongodb 드라이버가 제공하는 내장 함수를 사용하면 타임 스탬프별로 쿼리 할 수 ​​있습니다.

var timestamp = Date.now();
var objectId = ObjectID.createFromTime(timestamp / 1000);

또는 현재 시간 전에 레코드를 검색하려면 다음을 수행하십시오.

var objectId = new ObjectID(); // or ObjectId in the mongo shell

출처 : http://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html


3
이것은 자바 스크립트 환경의 타임 스탬프에서 ObjectId를 만드는 가장 쉽고 쉬운 방법입니다. 연산은 ... 요청 것입니다 어느
앤더스 Östman

34

에서 다음 pymongo과 같이 할 수 있습니다.

import datetime
from bson.objectid import ObjectId
mins = 15
gen_time = datetime.datetime.today() - datetime.timedelta(mins=mins) 
dummy_id = ObjectId.from_datetime(gen_time)
result = list(db.coll.find({"_id": {"$gte": dummy_id}}))

datetime.datetime.utcnow () 또는 datetime.datetime.today ()를 사용하면 동일한 결과가 반환됩니다. 날짜 시간이 처리됩니다.
radtek

또는 pymongo종속성 을 사용하지 않고 : epoch_time_hex = format(int(time.time()), 'x') (쿼리에 0을 추가하는 것을 잊지 마십시오) 시간 패키지가 사용되었습니다 ( import time).
VasiliNovikov

OP가 자바 스크립트를 요구한다는 것을 알고 있지만 실제로 코드를 단순화하는 데 도움이되었습니다. 감사.
Fred S

14

ObjectId의 처음 4 바이트 는 timestamp를 나타내 므로 컬렉션을 시간순으로 쿼리하려면 간단히 id로 정렬하십시오.

# oldest first; use pymongo.DESCENDING for most recent first
items = db.your_collection.find().sort("_id", pymongo.ASCENDING)

문서를 얻은 후 다음 과 같이 ObjectId의 생성 시간을 얻을 수 있습니다 .

id = some_object_id
generation_time = id.generation_time

1
실제로 ObjectId에 포함 된 시간을 사용하여 특정 시간 전에 생성 된 객체 수를 얻는 것과 같은 작업을 수행 할 수있는 것을 원했지만 직접 액세스 할 수없는 것처럼 보입니다. 감사.
Zach

1
그렇게 할 수 있습니다. Leftium의 답변을보십시오.
atp

13

명령을 찾는 방법 (이 날짜 [2015-1-12]부터이 날짜 [2015-1-15]) :

db.collection.find ({_ id : {$ gt : ObjectId (Math.floor ((new Date ( '2015/1/12')) / 1000) .toString (16) + "0000000000000000"), $ lt : ObjectId (Math.floor ((새 날짜 ( '2015/1/15')) / 1000) .toString (16) + "0000000000000000")}}). pretty ()

명령을 세십시오 (이 날짜 [2015-1-12]부터이 날짜 [2015-1-15]) :

db.collection.count ({_ id : {$ gt : ObjectId (Math.floor ((new Date ( '2015/1/12')) / 1000) .toString (16) + "0000000000000000"), $ lt : ObjectId (Math.floor ((새 날짜 ( '2015/1/15')) / 1000) .toString (16) + "0000000000000000")}))

명령을 제거하십시오 (이 날짜 [2015-1-12]부터이 날짜 [2015-1-15]까지) :

db.collection.remove ({_ id : {$ gt : ObjectId (Math.floor ((new Date ( '2015/1/12')) / 1000) .toString (16) + "0000000000000000"), $ lt : ObjectId (Math.floor ((새 날짜 ( '2015/1/15')) / 1000) .toString (16) + "0000000000000000")}))


10

$convert4.0 버전부터 ObjectId에서 날짜를 추출하는 함수를 사용할 수 있습니다 .

같은 것

$convert: { input: "$_id", to: "date" } 

날짜의 시작 시간과 종료 시간을 비교하여 날짜를 쿼리 할 수 ​​있습니다.

db.collectionname.find({
  "$expr":{
    "$and":[
      {"$gte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2018-07-03T00:00:00.000Z")]},
      {"$lte":[{"$convert":{"input":"$_id","to":"date"}}, ISODate("2018-07-03T11:59:59.999Z")]}
    ]
  }
})

또는

속기 $toDate를 사용 하여 동일한 결과를 얻을 수 있습니다 .

db.collectionname.find({
  "$expr":{
    "$and":[
      {"$gte":[{"$toDate":"$_id"}, ISODate("2018-07-03T00:00:00.000Z")]},
      {"$lte":[{"$toDate":"$_id"},ISODate("2018-07-03T11:59:59.999Z")]}
    ]
  }
})

$ convert 또는 $ toDate를 사용하여 물어보고 싶었을 때 Mongo는 먼저 doc가 범위 내에 있는지 여부를 변환 한 다음 비교해야하지만 허용되는 답변의 접근 방식을 사용하면 날짜를 ObjectId로 변환하면됩니다. 클라이언트 측에서 단 한 번만 솔루션이 이보다 더 효율적이라고 생각하지 않습니까? 어쨌든이 두 연산자가 존재한다는 것을 알려 주셔서 감사합니다 :)
Sudhanshu Gaur

7

몽고 컬렉션에서 지난 60 일 된 문서를 얻으려면 셸에서 아래 쿼리를 사용했습니다.

db.collection.find({_id: {$lt:new ObjectId( Math.floor(new Date(new Date()-1000*60*60*24*60).getTime()/1000).toString(16) + "0000000000000000" )}})

1
$ lt 대신 $ gt를 사용하십시오. 그렇지 않으면, (60 일 전) 삽입 된 문서를 찾습니다.
yoooshi

1
@Vivek ObjectId 의 처음 4 바이트 는 유닉스 시대 (1970/1/1 00:00:00 UTC) 이후의 시간 (초)을 나타내므로 ($ gt)보다 크고 ($)보다 작게 사용할 수 있습니다. lt) 특정 창 내에서 생성 된 객체를 찾습니다.
John

5

범위 쿼리를 작성하려면 이 게시물 에서와 같이 수행 할 수 있습니다 . 예를 들어 특정 날짜 (예 : 2015 년 4 월 4 일)에 대한 쿼리 :

> var objIdMin = ObjectId(Math.floor((new Date('2015/4/4'))/1000).toString(16) + "0000000000000000")
> var objIdMax = ObjectId(Math.floor((new Date('2015/4/5'))/1000).toString(16) + "0000000000000000")
> db.collection.find({_id:{$gt: objIdMin, $lt: objIdMax}}).pretty()


2

MongoObjectID를 사용하면 다음과 같이 결과를 찾을 수 있습니다

db.mycollection.find({ _id: { $gt: ObjectId("5217a543dd99a6d9e0f74702").getTimestamp().getTime()}});

3
쿼리 문은 ObjectId 값을 알고 있다고 가정합니다. 항상 그런 것은 아닙니다.
Dwight Spencer

0

레일에서 mongoid다음을 사용하여 쿼리 할 수 ​​있습니다.

  time = Time.utc(2010, 1, 1)
  time_id = ObjectId.from_time(time)
  collection.find({'_id' => {'$lt' => time_id}})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.