다른 포스트에서도 다룬 바 있으나 조금 더 자세하게 알아보자.
대전제 : 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}})
'DB, ORM > 🍃 mongoDB (shell)' 카테고리의 다른 글
집계 명령어 활용하기 (1) 몽고 DB의 아키텍쳐와 집계의 효율성 (0) | 2020.07.24 |
---|---|
projection 연산자 (0) | 2020.07.24 |
원자성을 유지를 위한 Transaction(트랜잭션) + WriteConcern/ReadConcern (0) | 2020.07.24 |
Robo 3T 설치 및 활용 (0) | 2020.06.08 |
ubuntu에서 mongodb 설치하기 (0) | 2020.06.08 |