ObjectId로 날짜 범위 검색하기
ObjectId의 구조
ObjectId의 구조는 다음과 같다.
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
},
}
)
- 4바이트까지 UnitTimestamp를 16진수로 변환한 후 나머지 8바이트를 0으로 채운다.
- Math.floor를 하는 이유는 소수점을 버리기 위함이다.
- 날짜 조회처럼 범위검색을 한다.
실제 사례
회사 정보 마스킹
번외) 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() 를 통해 얻을 수 있다.