ObjectId의 구조

ObjectId의 구조는 다음과 같다.

ObjectId 12바이트 구조 ObjectId의 12바이트 구조: Timestamp(4) + Random Value(5) + Counter(3)

  • 첫 번째 4byte: Unix epoch 이후 초 단위로 측정된 ObjectId의 생성을 나타내는 4바이트 타임스탬프 값
  • 두 번째 5byte: 프로세스당 한 번 생성 되는 5바이트 임의 값이며 이 임의 값은 기계와 프로세스에 고유
  • 세 번째 3byte: 임의의 값으로 초기화 되는 3바이트 증분 카운터

날짜 범위 검색 쿼리

첫 4Bytes가 UNIX Timestamp면 충분히 범위 검색이 가능하지 않을까? 라고 생각했고 아래와 같이 쿼리를 작성해봤다.

const startDate = new ISODate("2024-06-21T00:00:00+09:00");
const endDate = new ISODate("2024-06-21T17:35:00+09:00");

var startObjectId = ObjectId(Math.floor(startDate / 1000).toString(16) + "0000000000000000");
var endObjectId = ObjectId(Math.floor(endDate / 1000).toString(16) + "0000000000000000");

db.조회할컬렉션.find(
    {
        _id: {
            $gte: startObjectId,
            $lte: endObjectId
        },
    }
)
  1. 4바이트까지 UnitTimestamp를 16진수로 변환한 후 나머지 8바이트를 0으로 채운다.
    • Math.floor를 하는 이유는 소수점을 버리기 위함이다.
  2. 날짜 조회처럼 범위검색을 한다.

실제 사례

회사 정보 마스킹

번외) ObjectId에서 날짜 가져오기

Mongosh

ObjectId("507c7f79bcf86cd7994f6c0e").getTimestamp() // ISODate('2012-10-15T21:26:17.000Z')

mongosh 를 통한 스크립트에서 작동한다. 다만 DataGrip 2024.1.4 버전에서는 작동하지 않았다.

Java Mongo Driver

org.bson.types.ObjectId 에서 timestamp 값 혹은 getDate() 를 통해 얻을 수 있다.

웹사이트

Reference