Database/MongoDB 실습

[MongoDB] 멀티 키 인덱스 범위조건 사용하는 방법

꽁담 2024. 8. 6. 14:28

1. MongoDB 멀티인덱스

MongoDB 인덱스에서 멀티 키 인덱스는 여러 개의 인덱스 키 엔트리가 하나의 도큐먼트를 가지기 때문에

쿼리의 검색조건으로 멀티 키 인덱스를 사용할 때는 검색 조건을 주의해야 한다.

 

2. MongoDB 테스트 버전

유형 버전 구성
mongosh 2.2.10  
mongodb 7.0.12 Config : 1개, 포트 20000
Route : 1개, 포트 20001
Shard1 : 1개, 포트 30001
Shard2 : 1개, 포트 40001

 

 

3. MongoDB 테스트 데이터 적재

number 필드는 배열로 되어있고 number 필드를 인덱스로 생성했다.

[direct: mongos] indexDB> db.multiCollection.insert({ item: "Mozi" , number : [2, 9] })
{
  acknowledged: true,
  insertedIds: { '0': ObjectId('66b1b1a4eba581d9fa1b157d') }
}

[direct: mongos] indexDB> db.multiCollection.insert({ item: "Blog" , number : [4, 3] })
{
  acknowledged: true,
  insertedIds: { '0': ObjectId('66b1b1b2eba581d9fa1b157e') }
}

[direct: mongos] indexDB> db.multiCollection.createIndex( { number : 1 } )
number_1

 

 

4. MongoDB 멀티 키 테스트

4-1. 범위조건 테스트

BETWEEN 조건 3 보다 크고 6보다 작은 범위를 검색해본다.

그런데 2, 9 의 값을 가진 도큐먼트도 출력이 된다.

[direct: mongos] indexDB> db.multiCollection.find ( { number : { $gte : 3 , $lte : 6 } } )
[
  {
    _id: ObjectId('66b1b1a4eba581d9fa1b157d'),
    item: 'Mozi',
    number: [ 2, 9 ]
  },
  {
    _id: ObjectId('66b1b1b2eba581d9fa1b157e'),
    item: 'Blog',
    number: [ 4, 3 ]
  }
]

 

이유는 멀티 키 인덱스에 대한 조건을 각가 따로 비교한 다음에 두 개의 결과를 병합(합집합)하기 때문이다.

즉, 3보다 큰 값이 있기에 9 가 대상이 되고 6보다 작은 값이 있기에 2가 대상이 된다.

 

4-2. $elemMatch 연산사용

MongoDB 에서 elemMatch 연산을 사용하면 BETWEEN 와 같다. (교집합)

3보다 작은 값(=2)이 있기때문에, 그리고 6보다 큰 값(=9) 가 있기 때문에 item 이 Mozi 인 도큐먼트는 출력되지 않는다.

[direct: mongos] indexDB> db.multiCollection.find ( { number : { $elemMatch : { $gte : 3 , $lte : 6 } } } )
[
  {
    _id: ObjectId('66b1b1b2eba581d9fa1b157e'),
    item: 'Blog',
    number: [ 4, 3 ]
  }
]

 

하지만 두 조건을 모두 만족하는 엘리먼트를 하나라도 가지고 있다면 결과로 반환된다.

즉 6보다 작은 값(2, 4)을 모두 만족하기 때문에 item 이 Tistory 가 출력이 된다.

[direct: mongos] indexDB> db.multiCollection.insert({ item: "Tistory" , number : [2, 4] })
{
  acknowledged: true,
  insertedIds: { '0': ObjectId('66b1b386eba581d9fa1b157f') }
}

[direct: mongos] indexDB> db.multiCollection.find ( { number : { $elemMatch : { $gte : 3 , $lte : 6 } } } )
[
  {
    _id: ObjectId('66b1b1b2eba581d9fa1b157e'),
    item: 'Blog',
    number: [ 4, 3 ]
  },
  {
    _id: ObjectId('66b1b386eba581d9fa1b157f'),
    item: 'Tistory',
    number: [ 2, 4 ]
  }
]