예제로 이해하는 find 의 다양한 문법

7. 예제로 이해하는 find 의 다양한 문법

7.1. sort

  • mysql의 order by에 해당
  • find로 데이터 열람 시, 정렬 조건 명시 가능
# 기본적으로 오름차순
result = actor_collection.find().sort('actor_name')
for record in result:
    print(record)
result = actor_collection.find().sort('actor_name', pymongo.ASCENDING)
for record in result:
    print(record)
# 내림차순 명시
result = actor_collection.find().sort('actor_name', pymongo.DESCENDING)
for record in result:
    print(record)
# sort by multiple fields
result = actor_collection.find().sort([('actor_name', pymongo.ASCENDING),
                            ('actor_rate', pymongo.DESCENDING)])

for record in result:
    print(record)

7.2. 필드값이 존재하는 경우 검색 예제 (exists)

  • embedded document 의 경우 검색 예제 포함
for doc in actor_collection.find({'actor_info.특기' : {'$exists' : False}}):
    print(doc)
for doc in actor_collection.find({'actor_info.생년월일' : {'$exists' : False}}):
    print(doc)
for doc in actor_collection.find({'actor_info.홈페이지' : {'$exists' : True}}):
    print(doc)
실습
생년월일이 없는 doc의 actor_name 만 출력하기
for doc in actor_collection.find({'actor_info' : {'$exists' : True}}):
    print(doc)

7.3. 필드의 범위로 검색 예제

  • gt, gte
    • gt : 크다, gte : 크거나 같다
  • lt, lte
    • lt : 작다, lte : 작거나 같다
for doc in actor_collection.find({'actor_rate' : {'$gte' : 40000}}):
    print(doc)
for doc in actor_collection.find(
                    {'actor_rate' : {'$lte' : 70000}, 
                     'actor_name' : '설경구' }
                    ):
    print(doc)
실습
actor_rate 가 <= 35000 인 doc의 배우 이름과 배우가 출연한 영화 리스트 출력하기
for doc in actor_collection.find( { 'actor_rate' : {'$lte' : 35000} }, { 'actor_name': 1, 'movie_list': 1, '_id':0 } ):
    print(doc)

7.4. or

test_insert 컬렉션으로 테스트를 해보겠습니다. (age 컬럼 활용)

username = 'davelee'
password = 'korea123'
connection = pymongo.MongoClient('mongodb://%s:%s@www.funcoding.xyz' % (username, password))
db = connection.test
test_collection = db.test_collection
for result in test_collection.find():
    print(result)
for doc in test_insert_collection.find():
    print(doc)
for doc in test_insert_collection.find({'$or' : [ {'age' : 27}, {'age' : 30} ] }):
    print(doc)
# name이 aaron이고, age가 20이거나 30인 doc
for doc in test_insert_collection.find({ 'name' : 'aaron', '$or' : [ { 'age' : {'$lte' : 20 } }, { 'age' : 30 } ] }):
    print(doc)
for doc in test_insert_collection.find({'$or' : [ {'age' : { '$gte' : 29 } }, { 'age' : { '$lte' : 25 } } ] }):
    print(doc)
# age가 29 이상이거나 25인 doc
for doc in test_insert_collection.find( {'$or' : [ {'age' : {'$gte' : 29 } }, { 'age' : 25 } ] } ):
    print(doc)
  • 조건: age >= 27 or name = 'fox'
  • 출력: name, age
for doc in test_insert_collection.find( {'$or' : [ {'age' : {'$gte' : 27 } }, { 'name' : 'fox' } ] }, {'_id':0} ):
    print(doc)
# age가 29 이상이거나 25인 doc
for doc in test_insert_collection.find({'$or' : [ {'age' : {'$gte' : 27}}, {'name' : 'fox'}]}, {'name':1, 'age':1, '_id':0}):
    print(doc)

7.5. nor

  • not or
for doc in test_insert_collection.find({'$nor' : [{'age' : {'$gte' : 29}}, {'age' : 25}]}):
    print(doc)

7.6. in, nin

# age가 해당 리스트안에 존재하는 원소와 일치할 떄
for doc in test_insert_collection.find({'age' : {'$in' : [20, 21, 25, 27]}}):
    print(doc)
# nin : not in
for doc in test_insert_collection.find({'age' : {'$nin' : [20, 21, 25, 27]}}):
    print(doc)

7.7. skip, limit

  • skip(n) : 검색 결과 n개만큼 건너뜀
  • limit(n) : 검색 결과 n개로 제한
for doc in test_insert_collection.find({'age' : {'$nin' : [20, 21, 25, 27]}}).skip(3):
    print(doc)
for doc in test_insert_collection.find({'age' : {'$nin' : [20, 21, 25, 27]}}).limit(3):
    print(doc)
# skip limit 동시 사용 가능
for doc in test_insert_collection.find({'age' : {'$nin' : [20, 21, 25, 27]}}).skip(1).limit(3):
    print(doc)

7.7. list 검색

import pymongo

username = 'davelee'
password = 'korea123'
connection = pymongo.MongoClient('mongodb://%s:%s@www.funcoding.xyz' % (username, password))
mongodb = connection.cine21
actor_collection = mongodb.actor_collection
# 영화 리스트에 범죄도시를 포함하는 경우
for doc in actor_collection.find({'movie_list' : '범죄도시'}):
    print(doc['actor_name'])
# 영화 리스트에 범죄도시 또는 수상한 그녀를 포함하는 경우
for doc in actor_collection.find({'$or' : [{'movie_list' : '범죄도시'}, {'movie_list' : '수상한 그녀'}]}):
    print(doc['actor_name'])
# 영화 리스트에 범죄도시와 택시운전사를 포함하는 경우
for doc in actor_collection.find({'movie_list' : '범죄도시', 'movie_list' : '택시운전사'}):
    print(doc['actor_name'])
  • 리스트로 비교하기 위해서는 순서와 값이 정확히 일치해야 함
# 결과 없음
for doc in actor_collection.find({'movie_list' : ['부라더', '범죄도시']}):
    print(doc['actor_name'])
for doc in actor_collection.find({'movie_list' : ['범죄도시', '남한산성']}):
    print(doc['actor_name'])
  • 순서에 관계 없이 찾고자 하는 경우
# 영화 리스트에 부라더와 범죄도시를 순서와 관계없이 포함하는 경우
for doc in actor_collection.find({'movie_list' : {'$all' :  ['부라더', '범죄도시'] }} ):
    print(doc['actor_name'])
# 영화 리스트에 부라더와 범죄도시를 순서와 관계없이 포함하는 경우
for doc in actor_collection.find({'movie_list' : {'$all' :  ['택시운전사', '범죄도시'] }} ):
    print(doc['actor_name'])
# 영화 리스트에 수상한 그녀를 순서와 관계없이 포함하는 경우
for doc in actor_collection.find({'movie_list' : {'$all' :  ['수상한 그녀'] }} ):
    print(doc['actor_name'])
  • elemMatch
    • 적어도 한개 이상의 원소가 복수개의 조건을 동시에 만족하는 경우
    • 조건이 한개인 경우는 사용하지 않음
score = mongodb.test.score
for doc in score.find():
    print(doc)
score.insert_many([
{ 'results': [ 82, 85, 88 ] },
{ 'results': [ 75, 88, 91 ] }])
# 각 조건별로 하나라도 만족하는 원소가 있을 경우
for doc in score.find({'results' : { '$gte': 90, '$lt': 85 }}):
    print(doc)
# 적어도 한개의 원소(82) 가 모든 조건을 만족하는 경우 (80 <= 82 <= 85)
for doc in score.find({'results' :  {'$elemMatch' : { '$gte': 80, '$lt': 85 }}}):
    print(doc)
  • 인덱스를 특정하여 검색하기
# movie_list의 1번째 원소가 범죄도시인 것 검색
for doc in actor_collection.find({'movie_list.0' : '범죄도시'} ):
    print(doc['actor_name'])
# movie_list의 2번째 원소가 범죄도시인 것 검색
for doc in actor_collection.find({'movie_list.1' : '범죄도시'} ):
    print(doc['actor_name'])
  • 리스트의 원소의 개수를 기준으로 검색 (정확한 개수로만 검색 가능)
for doc in actor_collection.find({'movie_list' : {'$size' : 3}} ):
    print(doc['actor_name'])

7.8. Update 예제

result = actor_collection.update_one(
    {'actor_name' : '마동석'}, 
    {
        '$set' : 
        {
            'actor_info.생년월일' : '1971-03-03', 
            'actor_info.홈페이지' : 'https://www.instagram.com/madongseok'
        }
    }
)
result.modified_count
# update_many로 매칭되는 모든 doc 업데이트
result = actor_collection.update_many({'actor_info.성별' : '남'}, {'$set' : {'actor_info.성별' : '남자'}})
result.modified_count
# update_many로 매칭되는 모든 doc 업데이트
result = actor_collection.update_many({'actor_info.성별' : '여'}, {'$set' : {'actor_info.성별' : '여자'}})
result.modified_count
for doc in actor_collection.find():
    print(doc)
  • upsert option
    • update method의 upsert parameter가 True로 전달하면, 매칭되는 document를 찾지 못한 경우, insert 수행
result = actor_collection.update_many({'actor_name' : '오달수'}, 
                           {'$set' : {'actor_name' : '오달수', 'actor_rate' : 42230}}, 
                           upsert=True)
result.modified_count
dir(result)
# 새로 삽입된 객체의 아이디
result.upserted_id
result = actor_collection.update_one({'actor_name' : '류승룡'}, 
                           {'$set' : {'actor_name' : '류승룡', 'actor_rate' : 42230}}, 
                           upsert=True)
result.modified_count
# 새로 삽입된 객체의 아이디
result.upserted_id
result = actor_collection.update_one({'actor_name' : '유해진'}, 
                           {'$set' : {'actor_name' : '유해진', 'actor_rate' : 42230}}, 
                           upsert=True)
# 새로 삽입된 객체의 아이디
result.upserted_id
for doc in actor_collection.find():
    print(doc)

7.9. Delete 예제

result = actor_collection.delete_one({'actor_name' : '오달수'})
print (result.deleted_count)

result = actor_collection.delete_many({'name' : '오바마'})
print (result.deleted_count)
result = actor_collection.delete_one({'actor_name' : '오달수'})
result = actor_collection.delete_many({'actor_rate' : 42230})
for doc in actor_collection.find():
    print(doc)