본문으로 바로가기

다른 포스트에서도 다룬 바 있으나 조금 더 자세하게 알아보자.

 

대전제 :  db.collection.find({condition}, {projection}, {option}) 

 

 

기본 활용

 

간단한 검색 + projection

db.by_road_type.find({county: "강릉시"}, {"교차로내.accident_count": 1})

객체 형태의 값은 "필드.속성" 으로

db.by_road_type.find({"기타단일로.death_toll": 0.0}, {"county": 1})

 

쿼리 연산자

 

쿼리가 복잡해지면 헷갈리는데, 쿼리의 가장 바깥 쪽에는 $and, $or, $nor이 온다는 것을 기억하자.

$eq     =    Matches values that are equal to a specified value. 
$ne     !=   Matches all values that are not equal to a specified value. 

$gt     >    Matches values that are greater than a specified value. 
$gte    >=   Matches values that are greater than or equal to a specified value.

$lt     <    Matches values that are less than a specified value. 
$lte    <=   Matches values that are less than or equal to a specified value. 


$in          주어진 배열 안에 속하는 값.  (배열에서 사용)
$nin         주어진 배열 안에 속하지 않는 값. (배열에서 사용)

$and 	조건 모두를 만족하는
$or  	조건 중 하나라도 만족하는
$nor 	조건 중 모든 것을 만족하지 않는
$not  	조건을 만족하지 않는
db.by_type.find({type: "차대차", accident_count: {$gte: 100}, death_toll: 0}, {"city_or_province": 1, "county": 1})
// type이 차대 사람이고(and) death_toll이 0이거나 heavy_injury가 0인 도큐먼트를 출력해라.
db.by_type.find({type: "차대사람", $or: [{death_toll: 0}, {heavy_injury: 0}]})

 

 

문자열 연산자

 

$regex	정규식
$text	문자열 검색

 

단순히 정규식을 사용하려면 regex를 생략해도 된다.

db.area.find({county: {$regex: /시$/}})
db.area.find({county: /시$/})
db.area.find({county: /군$/, population: {$gte: 100000}})

 

country 필드가 '구'로 끝나고, 첫 글자의 초성이 ㅇ인 도큐먼트를 출력합니다.

ㅇ으로 시작하는 가장 작은 음절이 '아' 이므로 '아'보다 크고, '자' 보다 작으면 초성이 ㅇ인 도큐먼트를 찾아낼 수 있겠죠

db.area.find({county:{$regex: /구$/, $gte: "아", $lt:"자"}})

 

$text를 잘 사용하려면 (사실상 필수) 인덱스를 생성해야 한다.

pymongo를 이용해 인덱스를 생성한 포스트를 첨부한다.

https://darrengwon.tistory.com/454

 

인덱스는 필드 값을 기반으로 도큐먼트를 가리키는 포인터 값으로 이뤄진 B-Tree 구조를 만든다. 이러한 자료 구조로 인덱스를 이용해 적은 연산으로 쿼리를 수행할 수 있다. (결과를 빨리 반환한다는 말이다!)

 

db.collection.find({$text: {$search : "찾고자하는검색어"}})

// 띄어쓰기로 여러 단어 (or) 검색
db.collection.find({$text: {$search : "단어1 단어2 단어3"}})

// 이스케이프를 통해 띄어쓰기 까지 문자열로 간주
db.collection.find({$text: {$search : "\"단어1 단어2 단어3\""}})

// $search 외의 여러 설정값
db.collection.find({$text: {$search : "", $language: "", $caseSensitive: bool, $diacriticSensitive: bool}})

 

 

배열 연산자

 

$all	순서와 상관없이 있으면 선택
$elemMatch	조건과 맞는 배열 속 요소를 가진 것을 선택
$size	해당 배열의 큭기와 같은 것 선택

 

우선 연산자 없이는 다음과 같이 사용

// 도큐먼트
{item: "book", tags: ["blank", "red"]}
{item: "book", tags: ["red", "blank"]}
{item: "book", tags: ["blue"]}

// tags에 red가 들어간 도큐먼트 전부 출력
db.inventory.find({tags: "red"})

// tags가 "red", "blank" 둘 다 주어진 순서대로 가진 도큐먼트 전부 출력
db.inventory.find({tags: ["red", "blank"]})

 

$elemMatch

5 미만 and 10 초과인 값인 값을 가져오라는 논리적으로는 성립될 수 없는 조건이지만 mongoDB에서는 다른 방식으로 해서한다.

mongoDB에서는 10 초과인 값이 있는가? (11), 5 미만인 값이 있는가?(1) 둘 다 만족하므로 참이다. 이는 배열 전체를 따지는 mongoDB의 특유의 방식 때문이다.

 

그러나 $elemMatch를 사용하게 되면 배열의 요소 별로 해당 조건을 적용하게 된다.

즉, 1이 10 초과이고 5 미만인가? 거짓, 11이 10초과이고 5미만인가? 거짓. 따라서 거짓이다.

 

$elemMatch가 우리의 상식에 좀 더 적합하다.

// tags: [1, 11] 가정

db.collection.find({tags: {$gt: 10, $lt: 5}})
db.collection.find({tags: {$elemMatch: {$gt: 10, $lt: 5}}})
// 1월에 중부상자가 0명이고 2월에 사망자가 0명인 도큐먼트를 찾아라
db.by_month.find({$and: [
    {month_data: {$elemMatch: {month: "01월", heavy_injury: 0}}},
    {month_data: {$elemMatch: {month: "02월", death_toll: 0}}}
 ]})

 

$all

// "red", "blank" 순서 중요
db.inventory.find({tags: ["red", "blank"]})

// $all을 쓰면 "red", "blank" 순서와 상관 없이 해당 요소가 있는지만 확인
db.collection.find({tags: {$all: ["red", "blank"]}})

 

배열 length가 3인 도큐먼트

db.collection.find({tags: {$size: 3}})

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체