시리즈: NoSQL
python
548 줄
· 업데이트 2026-02-03
06_advanced_operations.py
NoSQL/python-examples/06_advanced_operations.py
"""
MongoDB Python Integration - Advanced Operations
=================================================
This module demonstrates advanced MongoDB operations including:
- Aggregation Pipeline
- Indexes
- Text Search
- Transactions
- Bulk Operations
- GridFS (for large files)
"""
from pymongo import MongoClient, ASCENDING, DESCENDING, TEXT
from pymongo.errors import BulkWriteError, DuplicateKeyError
from datetime import datetime, timedelta
from pprint import pprint
import json
def connect_to_mongodb():
"""Connect to MongoDB and return database object."""
try:
client = MongoClient("mongodb://localhost:27017/", serverSelectionTimeoutMS=5000)
client.admin.command('ping')
db = client["training_db"]
print("✓ Connected to MongoDB")
return client, db
except Exception as e:
print(f"✗ Connection error: {e}")
return None, None
def aggregation_pipeline_example(db):
"""
Demonstrate MongoDB aggregation pipeline.
Args:
db: Database object
"""
print("\n" + "=" * 50)
print("Aggregation Pipeline")
print("=" * 50)
collection = db["users"]
# Simple aggregation: Group by city
print("\n1. Group users by city:")
pipeline = [
{
"$group": {
"_id": "$city",
"totalUsers": {"$sum": 1},
"avgAge": {"$avg": "$age"},
"maxAge": {"$max": "$age"},
"minAge": {"$min": "$age"}
}
},
{
"$sort": {"totalUsers": -1}
}
]
results = list(collection.aggregate(pipeline))
for result in results:
print(f" {result['_id']}: {result['totalUsers']} users, "
f"avg age: {result['avgAge']:.1f}")
# Complex aggregation: Active users by city with age range
print("\n2. Active users statistics by city:")
pipeline = [
{"$match": {"isActive": True}},
{
"$group": {
"_id": "$city",
"count": {"$sum": 1},
"avgAge": {"$avg": "$age"},
"users": {
"$push": {
"name": "$name",
"age": "$age"
}
}
}
},
{"$sort": {"count": -1}},
{"$limit": 5}
]
results = list(collection.aggregate(pipeline))
for result in results:
print(f"\n City: {result['_id']}")
print(f" Count: {result['count']}, Avg Age: {result['avgAge']:.1f}")
# Aggregation with unwind (flatten arrays)
print("\n3. Unwind hobbies to see all hobbies:")
pipeline = [
{"$unwind": "$hobbies"},
{
"$group": {
"_id": "$hobbies",
"count": {"$sum": 1}
}
},
{"$sort": {"count": -1}}
]
results = list(collection.aggregate(pipeline))
print(" Top hobbies:")
for result in results[:5]:
print(f" {result['_id']}: {result['count']} users")
# Aggregation with project and addFields
print("\n4. Calculate age group:")
pipeline = [
{
"$addFields": {
"ageGroup": {
"$switch": {
"branches": [
{"case": {"$lt": ["$age", 25]}, "then": "Young"},
{"case": {"$lt": ["$age", 35]}, "then": "Adult"},
{"case": {"$lt": ["$age", 50]}, "then": "Middle-aged"},
{"case": {"$gte": ["$age", 50]}, "then": "Senior"}
],
"default": "Unknown"
}
}
}
},
{
"$group": {
"_id": "$ageGroup",
"count": {"$sum": 1}
}
},
{"$sort": {"count": -1}}
]
results = list(collection.aggregate(pipeline))
print("\n Users by age group:")
for result in results:
print(f" {result['_id']}: {result['count']} users")
def index_operations(db):
"""
Demonstrate index creation and usage.
Args:
db: Database object
"""
print("\n" + "=" * 50)
print("Index Operations")
print("=" * 50)
collection = db["users"]
# List existing indexes
print("\n1. Existing indexes:")
indexes = collection.list_indexes()
for index in indexes:
print(f" {index['name']}: {index.get('key', {})}")
# Create single field index
print("\n2. Creating index on 'email' field:")
try:
collection.create_index("email", unique=True)
print(" ✓ Index created on email (unique)")
except Exception as e:
print(f" Note: {e}")
# Create compound index
print("\n3. Creating compound index on 'city' and 'age':")
collection.create_index([("city", ASCENDING), ("age", DESCENDING)])
print(" ✓ Compound index created")
# Create text index
print("\n4. Creating text index on 'name' and 'email':")
try:
collection.create_index([("name", TEXT), ("email", TEXT)])
print(" ✓ Text index created")
except Exception as e:
print(f" Note: {e}")
# Get index information
print("\n5. All indexes:")
indexes = list(collection.list_indexes())
for index in indexes:
print(f" {index['name']}: {index.get('key', {})}")
# Explain query to see index usage
print("\n6. Query execution plan (using index):")
explain_result = collection.find({"email": "john.doe@example.com"}).explain()
execution_stats = explain_result.get('executionStats', {})
print(f" Execution time: {execution_stats.get('executionTimeMillis', 'N/A')} ms")
print(f" Documents examined: {execution_stats.get('totalDocsExamined', 'N/A')}")
print(f" Documents returned: {execution_stats.get('nReturned', 'N/A')}")
def text_search_example(db):
"""
Demonstrate text search functionality.
Args:
db: Database object
"""
print("\n" + "=" * 50)
print("Text Search")
print("=" * 50)
collection = db["users"]
# Ensure text index exists
try:
collection.create_index([("name", TEXT), ("email", TEXT)])
except:
pass # Index might already exist
# Text search
print("\n1. Text search for 'John':")
results = collection.find({"$text": {"$search": "John"}})
for user in results:
print(f" {user.get('name')} - {user.get('email')}")
# Text search with score
print("\n2. Text search with relevance score:")
results = collection.find(
{"$text": {"$search": "john doe"}},
{"score": {"$meta": "textScore"}}
).sort([("score", {"$meta": "textScore"})])
for user in results:
score = user.get('score', 0)
print(f" {user.get('name')} - Score: {score:.2f}")
def bulk_operations_example(db):
"""
Demonstrate bulk write operations.
Args:
db: Database object
"""
print("\n" + "=" * 50)
print("Bulk Operations")
print("=" * 50)
collection = db["bulk_test"]
# Clear collection
collection.delete_many({})
# Prepare bulk operations
operations = [
# Insert operations
{
"insertOne": {
"document": {"name": "Bulk User 1", "value": 1}
}
},
{
"insertOne": {
"document": {"name": "Bulk User 2", "value": 2}
}
},
# Update operations
{
"updateOne": {
"filter": {"name": "Bulk User 1"},
"update": {"$set": {"value": 10}}
}
},
{
"updateMany": {
"filter": {"value": {"$lt": 5}},
"update": {"$set": {"status": "active"}}
}
},
# Replace operation
{
"replaceOne": {
"filter": {"name": "Bulk User 2"},
"replacement": {"name": "Bulk User 2", "value": 20, "updated": True}
}
},
# Delete operation
{
"deleteOne": {
"filter": {"value": {"$gt": 15}}
}
}
]
print("\n1. Executing bulk write operations:")
try:
result = collection.bulk_write(operations, ordered=False)
print(f" Inserted: {result.inserted_count}")
print(f" Updated: {result.modified_count}")
print(f" Deleted: {result.deleted_count}")
print(f" Upserted: {result.upserted_count}")
except BulkWriteError as e:
print(f" Some operations failed: {e.details}")
# Show results
print("\n2. Documents after bulk operations:")
for doc in collection.find():
print(f" {doc}")
def transaction_example(db):
"""
Demonstrate transactions (MongoDB 4.0+).
Args:
db: Database object
"""
print("\n" + "=" * 50)
print("Transactions")
print("=" * 50)
client = db.client
# Start a session
with client.start_session() as session:
try:
# Start transaction
with session.start_transaction():
users_collection = db["users"]
accounts_collection = db["accounts"]
print("\n1. Creating user and account in transaction:")
# Create user
user_result = users_collection.insert_one(
{
"name": "Transaction User",
"email": "transaction@example.com",
"createdAt": datetime.now()
},
session=session
)
print(f" User created: {user_result.inserted_id}")
# Create account
account_result = accounts_collection.insert_one(
{
"userId": user_result.inserted_id,
"balance": 1000,
"createdAt": datetime.now()
},
session=session
)
print(f" Account created: {account_result.inserted_id}")
# Commit transaction
session.commit_transaction()
print(" ✓ Transaction committed")
except Exception as e:
# Abort transaction on error
session.abort_transaction()
print(f" ✗ Transaction aborted: {e}")
def find_with_projection_advanced(db):
"""
Advanced projection examples.
Args:
db: Database object
"""
print("\n" + "=" * 50)
print("Advanced Projection")
print("=" * 50)
collection = db["users"]
# Project with array slice
print("\n1. Project with array slice (first 2 hobbies):")
users = collection.find({}, {"name": 1, "hobbies": {"$slice": 2}})
for user in users.limit(3):
print(f" {user.get('name')}: {user.get('hobbies', [])}")
# Project with conditional
print("\n2. Project with computed field:")
pipeline = [
{
"$project": {
"name": 1,
"age": 1,
"isSenior": {"$gte": ["$age", 50]},
"ageGroup": {
"$cond": {
"if": {"$lt": ["$age", 30]},
"then": "Young",
"else": "Adult"
}
}
}
}
]
results = list(collection.aggregate(pipeline))
for result in results[:3]:
print(f" {result.get('name')}: {result.get('ageGroup')}, "
f"Senior: {result.get('isSenior')}")
def date_operations_example(db):
"""
Demonstrate date operations and queries.
Args:
db: Database object
"""
print("\n" + "=" * 50)
print("Date Operations")
print("=" * 50)
collection = db["users"]
# Find users created in last 7 days
print("\n1. Users created in last 7 days:")
seven_days_ago = datetime.now() - timedelta(days=7)
recent_users = collection.find({
"createdAt": {"$gte": seven_days_ago}
})
count = 0
for user in recent_users:
count += 1
print(f" {user.get('name')} - {user.get('createdAt')}")
if count == 0:
print(" (No recent users found)")
# Group by date (day)
print("\n2. Users grouped by creation date:")
pipeline = [
{
"$group": {
"_id": {
"$dateToString": {
"format": "%Y-%m-%d",
"date": "$createdAt"
}
},
"count": {"$sum": 1}
}
},
{"$sort": {"_id": -1}}
]
results = list(collection.aggregate(pipeline))
for result in results[:5]:
print(f" {result['_id']}: {result['count']} users")
def aggregation_with_lookup(db):
"""
Demonstrate $lookup (join) in aggregation.
Args:
db: Database object
"""
print("\n" + "=" * 50)
print("Aggregation with $lookup (Join)")
print("=" * 50)
# Create sample orders collection
orders_collection = db["orders"]
users_collection = db["users"]
# Insert sample orders
orders_collection.delete_many({})
user = users_collection.find_one()
if user:
orders_collection.insert_many([
{
"userId": user["_id"],
"product": "Laptop",
"amount": 999.99,
"date": datetime.now()
},
{
"userId": user["_id"],
"product": "Mouse",
"amount": 29.99,
"date": datetime.now()
}
])
# Lookup users for orders
print("\n1. Orders with user information:")
pipeline = [
{
"$lookup": {
"from": "users",
"localField": "userId",
"foreignField": "_id",
"as": "user"
}
},
{
"$unwind": "$user"
},
{
"$project": {
"product": 1,
"amount": 1,
"userName": "$user.name",
"userEmail": "$user.email"
}
}
]
results = list(orders_collection.aggregate(pipeline))
for result in results:
print(f" {result.get('product')} - ${result.get('amount')} - "
f"User: {result.get('userName')}")
# Main execution
if __name__ == "__main__":
print("=" * 50)
print("MongoDB Python - Advanced Operations")
print("=" * 50)
client, db = connect_to_mongodb()
if db:
# Run examples
aggregation_pipeline_example(db)
index_operations(db)
text_search_example(db)
bulk_operations_example(db)
transaction_example(db)
find_with_projection_advanced(db)
date_operations_example(db)
aggregation_with_lookup(db)
# Close connection
client.close()
print("\n" + "=" * 50)
print("All advanced operations completed!")
print("=" * 50)
관련 글
NoSQL
python
업데이트 2026-02-03
01_basic_connection.py
01_basic_connection.py — python source code from the NoSQL learning materials (NoSQL/python-examples/01_basic_connection.py).
글 읽기 →
NoSQL
python
업데이트 2026-02-03
02_create_operations.py
02_create_operations.py — python source code from the NoSQL learning materials (NoSQL/python-examples/02_create_operations.py).
글 읽기 →
NoSQL
python
업데이트 2026-02-03
03_read_operations.py
03_read_operations.py — python source code from the NoSQL learning materials (NoSQL/python-examples/03_read_operations.py).
글 읽기 →
NoSQL
python
업데이트 2026-02-03
04_update_operations.py
04_update_operations.py — python source code from the NoSQL learning materials (NoSQL/python-examples/04_update_operations.py).
글 읽기 →
NoSQL
python
업데이트 2026-02-03
05_delete_operations.py
05_delete_operations.py — python source code from the NoSQL learning materials (NoSQL/python-examples/05_delete_operations.py).
글 읽기 →