본문으로 바로가기

pymongo/mongoose 쿼리 작성하기

category DB, ORM/🍃mongoose, pymongo 2020. 6. 9. 16:11

pymongo 기준으로 썼지만 mongoose도 그렇게 다르지 않다.

여기서 참고하고 mongoose 문서 보면 뚝딱!

 

 

 

컬럼명 변경 $rename

 

actor_collection.update_many({}, {'$rename': {'다른 이름': '다른이름'}})

 

sort

 

sort의 문제점 중 하나는 해당 값이 없는 값도 가져온다는 점입니다. 아래 코드의 경우 생년월일이 낮은 순서대로 가져오게 되는에 이 경우 생년월일이 없는 경우가 가장 낮은 도큐먼트가 먼저 불러져오게 됩니다.

for i in actor_collection.find({}).sort('생년월일').limit(5):
    print(i)

 

이를 방지하기 위해서는 정렬 기준을 명시해주면 됩니다. 내림차순(높은 값이 가장 먼저 나옵니다)으로 정렬해보았습니다.

for i in actor_collection.find({}).sort('생년월일', pymongo.DESCENDING).limit(5):
    print(i)

 

 

특정 속성이 있는 값만 추려내기 $exsits

 

for i in actor_collection.find({"특기": {"$exists": True}}):
    print(i)

 

 

비교연산자

 

""로 감싸주는 걸 잊지 맙시다. 여기는 shell이 아니라 ODM입니다.

for i in actor_collection.find({"흥행지수": {"$gte": 10000}}, {"배우이름": 1, "_id": 0}).limit(4):
    print(i)

 

find({조건}, {출력열}) 을 이용해서, 흥행지수가 10000 이상이고, 영화 '박쥐'에 출연한 조건에 만족하는 도큐먼트의 배우이름만을 출력해보았습니다.

for i in actor_collection.find({"흥행지수": {"$gte": 10000}, "출연영화": "박쥐"}, {"배우이름": 1, "_id": 0}):
    print(i)

 

 

$or

 

기본적으로 위에 준 조건들은 and 조건입니다. or 조건은 다음과 같이 사용합니다.

actor_collection.find({"$or": [{"출연영화": "마더"}, {"출연영화": "박쥐"}]})

 

위와 연계해서, 흥행지수가 10000 이상이면서 출연영화가 마더나 박쥐인 도큐먼트에서 배우이름 속성만 가져오게 해보았습니다.

 

괄호 때문에 헷갈리는데 find({조건}, {가져올 속성}) 만 기억하고 들여쓰기를 잘 해줍시다.

actor_collection.find(
  {"흥행지수": {"$gte": 10000}, "$or": [{"출연영화": "마더"}, {"출연영화": "박쥐"}]},
  {"배우이름": 1}
):

 

 

$nor 

 

사용법은 위의 $or과 똑같습니다. 

nor는 ~or이므로

~(조건 1 or 조건 2) = ~조건 1 And ~조건 2

가 됩니다.

 

즉 아래 코드는 흥행지수가 20000 미만이며 50 이상인 값만을 가져옵니다.

for i in actor_collection.find({"$nor": [{"흥행지수": {"$gte": 20000}}, {"흥행지수": {"$lt": 50}}]}, {'배우이름': 1, "_id": 0}):
    print(i)

 

 

$in / $nin

 

쉽게 말해 해당 값을 가지고 있느냐(in) 가지고 있지 않느냐(nin)이다.

주의할 점은 조건은 배열로 주어야 한다. 그렇지 않으면 $in/$nin needs an array 오류를 낸다.

for i in actor_collection.find({"배우이름": {"$in": ["신하균"]}}):
    print(i)

 

 

skip(n), limit(n)

 

skip은 처음 몇 개를 생략하고, limit은 해당 갯수만큼만 가져옵니다.

for i in actor_collection.find(
  {"흥행지수": {"$nin": [9182, 8439]}, "흥행지수": {"$lte": 10000} },
  {"배우이름": 1, "흥행지수": 1, "_id":0}
).skip(3):
    print(i)

 

 

$all과 리스트 검색

 

조건으로 리스트를 주게 되면 해당 리스트와 정확히 일치하는 도큐먼트만 가져오게 된다. (그래서 잘 안쓴다)

 

$all을 쓰면 해당 리스트 안에 들어 있는 값을 모두 가지고 있는 도큐먼트를 가져온다.

 

# 출연 영화가 복수는 나의 것인 것을 가져오라.
actor_collection.find({"출연영화": "복수는 나의 것"})

# 출연영화가 정확히 마더, 박쥐가 순서대로 들어간 것만 가져오라.
# 마더, 박쥐, 사바하 3개에 출연한 도큐먼트는 안 가져옴
# 박쥐, 마더는 순서가 다르기 때문에 안 가져옴
actor_collection.find({"출연영화": ["마더", "박쥐"]})

# 출연영화가 마더 혹은 박쥐가 들어 있는 도큐먼트를 가져와라
actor_collection.find({"$or": [{"출연영화":"마더"}, {"출연영화":"박쥐"}]})

# 출연 영화가 마더와 박쥐 둘 다 들어 있는 도큐먼트를 가져와라
# 리스트의 순서가 중요하지 않음.
# 마더, 박쥐, 사바하 3개에 출연한 도큐먼트도 가져옴
for i in actor_collection.find({"출연영화": {'$all': ['마더', '박쥐']}}):
    print(i)
    
# 리스트인 출연영화의 첫번째 인덱스가 '사바하'인 도큐먼트를 가져와라
for i in actor_collection.find({"출연영화.0": "사바하"}):
    print(i)
    
# 출연영화 리스트의 크기가 5인 도큐먼트만 가져와라
actor_collection.find({'출연영화': {'$size': 5}})

 

 

$elemMatch

(https://docs.mongodb.com/manual/reference/operator/query/elemMatch/)

 

 

{ _id: 1, results: [ 82, 85, 88 ] }

{ _id: 2, results: [ 75, 88, 89 ] }

 

elemmatch_sample.find({'results': { "$gte": 80, "$lt": 85 }}):
    print(i)

db.scores.find(
   { results: { $elemMatch: { $gte: 80, $lt: 85 } } }
)

 

첫번째 코드는

 

{'_id': ObjectId('5edf43536c43fc502fa90abc'), 'results': [82, 85, 88]}

{'_id': ObjectId('5edf43536c43fc502fa90abd'), 'results': [75, 88, 89]}

 

두번째 코드는

{'_id': ObjectId('5edf43536c43fc502fa90abc'), 'results': [82, 85, 88]}

 

왜일까? 왜냐하면

 

첫번째 코드는 다음과 같이 일을 처리한다.

[75, 88, 89]에서 80 이상인 원소가  88, 89가 있고, 85 미만인원소가 75가 있네. 각 조건에 만족하는 원소가 적어도 하나씩은 있으니 참이다. 즉, 조건을 배열 전체로 놓고 해석한다. 

 

반면 두번째 $elemMatch는 배열 속 원소 하나 하나에 조건을 적용한다. 75가 80 이상, 85 미만인가? 88이 80 이상, 85 미만인가? (원소 별로 따진다고 해서 이름이 'elemMatch'이다)

[75, 88, 89]에서 80 이상, 85 미만을 동시에 만족하는 원소가 하나라도 있나? 없네. 거짓이다. 

 

공식 문서 설명에서도 이와 같이 설명한다.

contains at least one element that is both greater than or equal to 80 and is less than 85.

both에 집중하자. 두 조건 모두를 만족시켜야 한다는 것이다.

 


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