PyMongo 데이터 수정
PyMongo 데이터 수정
MongoDB는 유연한 비정형(NoSQL) 데이터베이스로, 문서를 자유롭게 추가하고 수정할 수 있습니다. PyMongo는 MongoDB와 Python 간의 연결을 지원하며, 이를 통해 쉽게 데이터를 업데이트할 수 있습니다. 이 글에서는 PyMongo에서 update_one()
과 update_many()
메서드를 사용하여 문서를 수정하는 방법을 설명하겠습니다.
1. PyMongo 설치 및 기본 설정
먼저 PyMongo를 설치해야 합니다. 터미널에서 다음 명령어를 실행하세요:
pip install pymongo
설치가 완료되면, MongoDB 서버와 연결하기 위한 코드를 작성할 수 있습니다.
MongoDB localhost에 연결
from pymongo import MongoClient
# MongoDB 서버에 연결 (로컬호스트를 사용한 예)
= MongoClient('mongodb://localhost:27017/') client
위 코드에서 MongoClient
를 사용하여 MongoDB 서버와 연결합니다. localhost
는 로컬에서 실행 중인 MongoDB 서버를 의미하며, 기본 포트인 27017
을 사용합니다. 만약 원격 서버에 연결하려면 해당 서버의 IP 주소와 포트를 사용하면 됩니다.
MongoDB Atlas에 연결
MongoDB Atlas는 클라우드 기반의 MongoDB 서비스로, 다음과 같이 연결 문자열을 설정하여 사용할 수 있습니다:
from pymongo import MongoClient
# MongoDB Atlas 연결
= MongoClient("mongodb+srv://<username>:<password>@cluster0.mongodb.net/mydatabase?retryWrites=true&w=majority") client
주의: <username>
, <password>
, <dbname>
은 사용자의 MongoDB Atlas 계정에 맞게 수정해야 합니다.
#| echo: false
from pymongo import MongoClient
# MongoDB Atlas 연결
= MongoClient("mongodb+srv://gabrielwithhappy:lJR3LbMaRjkJpEJg@cluster0.gbyjc.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0") client
from pymongo import MongoClient
# 데이터베이스 선택
= client['testdb']
db
# 컬렉션 선택
= db['users']
users
# # 새로 생성된 문서만 출력되도록 collection에 저장된 문서를 모두 삭제
users.delete_many({})
# 테스트용 문서 목록
= [
userdata "name": "Alice", "age": 30, "email": "alice@example.com"},
{"name": "Bob", "age": 25, "email": "bob@example.com"},
{"name": "Charlie", "age": 35, "email": "charlie@example.com"},
{"name": "Daisy", "age": 28, "email": "daisy@example.com"},
{"name": "Eve", "age": 40, "email": "eve@example.com"},
{"name": "Frank", "age": 22}, # email 필드 없음
{"name": "Grace", "age": 50, "email": "grace@example.com"},
{"name": "Hank", "age": 20, "email": "hank@example.com"},
{
]
# 여러 문서 삽입
= users.insert_many(userdata)
result
# 전체 문서 조회
= users.find({})
updated_documents for document in updated_documents:
print(document)
{'_id': ObjectId('66f87b2c4efbafb3dc09140a'), 'name': 'Alice', 'age': 30, 'email': 'alice@example.com'}
{'_id': ObjectId('66f87b2c4efbafb3dc09140b'), 'name': 'Bob', 'age': 25, 'email': 'bob@example.com'}
{'_id': ObjectId('66f87b2c4efbafb3dc09140c'), 'name': 'Charlie', 'age': 35, 'email': 'charlie@example.com'}
{'_id': ObjectId('66f87b2c4efbafb3dc09140d'), 'name': 'Daisy', 'age': 28, 'email': 'daisy@example.com'}
{'_id': ObjectId('66f87b2c4efbafb3dc09140e'), 'name': 'Eve', 'age': 40, 'email': 'eve@example.com'}
{'_id': ObjectId('66f87b2c4efbafb3dc09140f'), 'name': 'Frank', 'age': 22}
{'_id': ObjectId('66f87b2c4efbafb3dc091410'), 'name': 'Grace', 'age': 50, 'email': 'grace@example.com'}
{'_id': ObjectId('66f87b2c4efbafb3dc091411'), 'name': 'Hank', 'age': 20, 'email': 'hank@example.com'}
위 코드를 통해 MongoDB 서버에 연결하고, testdb 데이터베이스와 users 컬렉션을 선택했습니다. 컬렉션이 존재하지 않는다면 MongoDB는 데이터를 삽입할 때 자동으로 컬렉션을 생성합니다.
2. update_one()
메서드로 한 개의 문서 수정
update_one()
메서드는 컬렉션에서 조건에 맞는 첫 번째 문서를 수정할 때 사용됩니다. update_one()
메서드는 두 개의 인자를 받습니다:
- 필터 조건: 어떤 문서를 수정할지 선택하는 조건입니다.
- 수정 명령: 어떤 값을 어떻게 수정할지를 지정하는 명령입니다.
다음은 name
이 “Alice”인 사용자의 나이를 35로 업데이트하는 예시입니다.
# 필터 조건 및 수정 명령
= {"name": "Alice"}
filter_query = {"$set": {"age": 35}}
update_command
# 한 개의 문서 수정
= users.update_one(filter_query, update_command)
result
# 결과 출력
= users.find(filter_query)
updated_documents for document in updated_documents:
print(document)
print(f"Matched {result.matched_count} document(s) and modified {result.modified_count} document(s).")
코드 설명:
filter_query
: 수정할 문서를 찾기 위한 조건입니다. 여기서는name
이 “Alice”인 문서를 선택합니다.update_command
: 수정할 내용을 나타냅니다.$set
연산자를 사용하여age
필드를 35로 수정합니다.result.matched_count
: 필터 조건과 일치하는 문서의 개수입니다.result.modified_count
: 실제로 수정된 문서의 개수입니다.
출력 예시:
{'_id': ObjectId('66f87b2c4efbafb3dc09140a'), 'name': 'Alice', 'age': 35, 'email': 'alice@example.com'}
Matched 1 document(s) and modified 1 document(s).
3. update_many()
메서드로 여러 문서 수정
update_many()
메서드는 조건에 맞는 여러 문서를 한 번에 수정할 때 사용됩니다. 사용법은 update_one()
과 동일하지만, 여러 문서를 수정한다는 점에서 차이가 있습니다.
다음은 age
가 30 이상인 모든 사용자의 status
필드를 “active”로 업데이트하는 예시입니다.
# 필터 조건 및 수정 명령
= {"age": {"$gte": 30}}
filter_query = {"$set": {"status": "active"}}
update_command
# 여러 문서 수정
= users.update_many(filter_query, update_command)
result
# 결과 출력
= users.find(filter_query)
updated_documents for document in updated_documents:
print(document)
print(f"Matched {result.matched_count} document(s) and modified {result.modified_count} document(s).")
코드 설명:
filter_query
: 여기서는age
필드가 30 이상인 모든 문서를 선택합니다.update_command
:status
필드를 “active”로 설정하는 업데이트 명령입니다.
출력 예시:
{'_id': ObjectId('66f87b874efbafb3dc091413'), 'name': 'Alice', 'age': 35, 'email': 'alice@example.com', 'status': 'active'}
{'_id': ObjectId('66f87b874efbafb3dc091415'), 'name': 'Charlie', 'age': 35, 'email': 'charlie@example.com', 'status': 'active'}
{'_id': ObjectId('66f87b874efbafb3dc091417'), 'name': 'Eve', 'age': 40, 'email': 'eve@example.com', 'status': 'active'}
{'_id': ObjectId('66f87b874efbafb3dc091419'), 'name': 'Grace', 'age': 50, 'email': 'grace@example.com', 'status': 'active'}
Matched 4 document(s) and modified 4 document(s).
4. 업데이트 후 문서 확인
업데이트가 성공했는지 확인하기 위해 업데이트된 문서를 조회할 수 있습니다.
# 업데이트된 문서 확인
= users.find_one({"name": "Alice"})
updated_user print(updated_user)
{'_id': ObjectId('66f87e2d9d1075b1d0c38c51'), 'name': 'Alice', 'age': 35, 'email': 'alice@example.com', 'status': 'active'}
이 코드는 name
이 “Alice”인 문서를 찾아 출력합니다.
5. 다양한 업데이트 연산자
MongoDB는 여러 업데이트 연산자를 지원하며, PyMongo에서도 이를 동일하게 사용할 수 있습니다. 자주 사용되는 연산자는 다음과 같습니다.
5.1 $set
: 필드 값을 지정된 값으로 설정
이미 본 것처럼 $set
연산자는 기존 필드를 업데이트하거나 새 필드를 추가하는 데 사용됩니다.
# name이 'Bob'인 문서의 email 필드를 업데이트
= users.update_one({"name": "Bob"}, {"$set": {"email": "newbob@example.com"}})
result
print(result)
= users.find({"name": "Bob"})
updated_documents for document in updated_documents:
print(document)
출력 예시
UpdateResult({'n': 1, 'electionId': ObjectId('7fffffff000000000000003a'), 'opTime': {'ts': Timestamp(1727563035, 22), 't': 58}, 'nModified': 1, 'ok': 1.0, '$clusterTime': {'clusterTime': Timestamp(1727563035, 22), 'signature': {'hash': b'T\x10\x13o\xe8k\xd0\xaci\xf544\xfa\xd5\xea\xc3\x94\x95\xe4\xd4', 'keyId': 7377426399050596418}}, 'operationTime': Timestamp(1727563035, 22), 'updatedExisting': True}, acknowledged=True)
{'_id': ObjectId('66f87d109d1075b1d0c38c37'), 'name': 'Bob', 'age': 25, 'email': 'newbob@example.com'}
5.2 $inc
: 필드 값을 증가 또는 감소
$inc
연산자는 숫자 필드를 지정된 값만큼 증가(양수) 또는 감소(음수)시킵니다.
# age 필드를 1만큼 증가
"name": "Charlie"}, {"$inc": {"age": 1}})
users.update_one({
print(result)
= users.find({"name": "Charlie"})
updated_documents for document in updated_documents:
print(document)
출력 예시
UpdateResult({'n': 1, 'electionId': ObjectId('7fffffff000000000000003a'), 'opTime': {'ts': Timestamp(1727563298, 27), 't': 58}, 'nModified': 1, 'ok': 1.0, '$clusterTime': {'clusterTime': Timestamp(1727563298, 27), 'signature': {'hash': b'C+\x07\x86\xe7\n\xf6\x9bg\xe1\xaa\x14%\xbf\xfb\xb3h\xde\xf2\x12', 'keyId': 7377426399050596418}}, 'operationTime': Timestamp(1727563298, 27), 'updatedExisting': True}, acknowledged=True)
{'_id': ObjectId('66f87e2d9d1075b1d0c38c53'), 'name': 'Charlie', 'age': 36, 'email': 'charlie@example.com', 'status': 'active'}
5.3 $unset
: 필드를 제거
$unset
연산자는 지정된 필드를 문서에서 제거합니다.
# email 필드를 제거
"name": "Daisy"}, {"$unset": {"email": ""}})
users.update_one({
print(result)
= users.find({"name": "Daisy"})
updated_documents for document in updated_documents:
print(document)
출력 예시
UpdateResult({'n': 1, 'electionId': ObjectId('7fffffff000000000000003a'), 'opTime': {'ts': Timestamp(1727563298, 27), 't': 58}, 'nModified': 1, 'ok': 1.0, '$clusterTime': {'clusterTime': Timestamp(1727563298, 27), 'signature': {'hash': b'C+\x07\x86\xe7\n\xf6\x9bg\xe1\xaa\x14%\xbf\xfb\xb3h\xde\xf2\x12', 'keyId': 7377426399050596418}}, 'operationTime': Timestamp(1727563298, 27), 'updatedExisting': True}, acknowledged=True)
{'_id': ObjectId('66f87e2d9d1075b1d0c38c54'), 'name': 'Daisy', 'age': 28}
5.4 $rename
: 필드 이름 변경
$rename
연산자는 필드의 이름을 변경합니다.
# 필드 이름 변경: 'age'를 'years_old'로 변경
"name": "Eve"}, {"$rename": {"age": "years_old"}})
users.update_one({
print(result)
= users.find({"name": "Eve"})
updated_documents for document in updated_documents:
print(document)
출력 예시
UpdateResult({'n': 1, 'electionId': ObjectId('7fffffff000000000000003a'), 'opTime': {'ts': Timestamp(1727563298, 27), 't': 58}, 'nModified': 1, 'ok': 1.0, '$clusterTime': {'clusterTime': Timestamp(1727563298, 27), 'signature': {'hash': b'C+\x07\x86\xe7\n\xf6\x9bg\xe1\xaa\x14%\xbf\xfb\xb3h\xde\xf2\x12', 'keyId': 7377426399050596418}}, 'operationTime': Timestamp(1727563298, 27), 'updatedExisting': True}, acknowledged=True)
{'_id': ObjectId('66f87e2d9d1075b1d0c38c55'), 'name': 'Eve', 'email': 'eve@example.com', 'status': 'active', 'years_old': 40}
5.5 $push
: 배열에 값 추가
$push
연산자는 배열 필드에 새 값을 추가합니다.
# scores 배열에 새 값 추가
"name": "Frank"}, {"$push": {"scores": 85}})
users.update_one({
print(result)
= users.find({"name": "Frank"})
updated_documents for document in updated_documents:
print(document)
** 코드 설명** - {“name”: “Frank”}: 이 필터 조건에 맞는 문서를 찾습니다. 즉, name 필드가 “Frank”인 문서를 찾습니다. - {“$push”: {“scores”: 85}}: $push 연산자를 사용하여 scores라는 배열 필드에 값을 추가합니다. 이 경우, 85가 scores 배열
에 추가됩니다. - 결과: 만약 Frank의 문서에 scores 필드가 이미 있다면, 배열에 85가 추가됩니다. 만약 scores 필드가 없다면, 배열을 생성한 후 85를 넣습니다.
출력 예시
UpdateResult({'n': 1, 'electionId': ObjectId('7fffffff000000000000003a'), 'opTime': {'ts': Timestamp(1727563298, 27), 't': 58}, 'nModified': 1, 'ok': 1.0, '$clusterTime': {'clusterTime': Timestamp(1727563298, 27), 'signature': {'hash': b'C+\x07\x86\xe7\n\xf6\x9bg\xe1\xaa\x14%\xbf\xfb\xb3h\xde\xf2\x12', 'keyId': 7377426399050596418}}, 'operationTime': Timestamp(1727563298, 27), 'updatedExisting': True}, acknowledged=True)
{'_id': ObjectId('66f87e2d9d1075b1d0c38c56'), 'name': 'Frank', 'age': 22, 'scores': [85]}