과제

📌Mongo DB 심화 5문제 with python

Chansman 2025. 3. 27. 17:05

📌 개념 정리

이 포스팅에서는 MongoDB를 활용한 데이터 삽입, 조회, 업데이트 및 집계(aggregation)에 대한 여러 문제를 다룹니다. 예제 코드와 함께 MongoDB의 기본적인 사용법을 익히고, 실용적인 쿼리를 통해 데이터베이스 관리 기술을 향상시킬 수 있습니다.


🚦 동작 원리 및 구조

  1. MongoDB 연결
    • MongoClient를 사용하여 로컬 MongoDB 서버에 연결합니다.
    • 데이터베이스와 컬렉션을 선택하여 작업을 진행합니다.
  2. 데이터 삽입
    • insert_many를 사용하여 여러 문서를 한 번에 삽입할 수 있습니다.
  3. 데이터 조회
    • find와 aggregate 메서드를 사용하여 조건에 맞는 데이터를 조회하고, 집계할 수 있습니다.
  4. 데이터 업데이트
    • update_many 메서드를 사용하여 조건에 맞는 데이터를 일괄 수정할 수 있습니다.

💻 코드 예시 및 흐름 분석

  1. 데이터 삽입
    • 먼저 MongoDB에 접속하여 books, movies, user_actions 컬렉션에 데이터를 삽입하는 코드입니다. 이 과정은 insert_data() 함수에서 수행됩니다.
    • 삽입된 데이터는 나중에 다양한 쿼리를 통해 조회 및 분석할 수 있습니다.
from pymongo import MongoClient
from datetime import datetime

def insert_data():
    client = MongoClient('mongodb://localhost:27017/')
    db = client.local  # 'local' 데이터베이스 사용

    # 책 데이터 삽입
    books = [
        {"title": "Kafka on the Shore", "author": "Haruki Murakami", "year": 2002},
        {"title": "Norwegian Wood", "author": "Haruki Murakami", "year": 1987},
        {"title": "1Q84", "author": "Haruki Murakami", "year": 2009}
    ]
    db.books.insert_many(books)

    # 영화 데이터 삽입
    movies = [
        {"title": "Inception", "director": "Christopher Nolan", "year": 2010, "rating": 8.8},
        {"title": "Interstellar", "director": "Christopher Nolan", "year": 2014, "rating": 8.6},
        {"title": "The Dark Knight", "director": "Christopher Nolan", "year": 2008, "rating": 9.0}
    ]
    db.movies.insert_many(movies)

    # 사용자 행동 데이터 삽입
    user_actions = [
        {"user_id": 1, "action": "click", "timestamp": datetime(2023, 4, 12, 8, 0)},
        {"user_id": 1, "action": "view", "timestamp": datetime(2023, 4, 12, 9, 0)},
        {"user_id": 2, "action": "purchase", "timestamp": datetime(2023, 4, 12, 10, 0)},
    ]
    db.user_actions.insert_many(user_actions)

    print("Data inserted successfully")
    client.close()

if __name__ == "__main__":
    insert_data()
  1. 장르 추가
    • 기존의 책 데이터에 "genre": "fantasy" 필드를 추가하는 코드입니다.
from pymongo import MongoClient

client = MongoClient('mongodb://localhost:27017/')
db = client.local  

# 장르 추가
db.books.update_many(
    {},  
    {"$set": {"genre": "fantasy"}}  
)

print("Genre field added to all books")
client.close()
  1. 문제 해결 예시
    • 문제 1: 특정 장르의 책 찾기
      • 문제 설명: 데이터베이스에 새로운 필드로 genre를 책 데이터에 추가하였습니다. 사용자는 "fantasy" 장르의 모든 책을 찾고 싶어합니다.
      • 쿼리 작성 목표: "fantasy" 장르에 해당하는 모든 책의 제목과 저자를 찾는 MongoDB 쿼리를 함수로 만들어 문제를 해결해 봅니다. 
      • "fantasy" 장르의 책을 찾는 쿼리입니다.
def find_books_by_genre(db, genre):
    query = {"genre": genre}
    projection = {"_id": 0, "title": 1, "author": 1}
    books = db.books.find(query, projection)
    for book in books:
        print(book)

find_books_by_genre(db, 'fantasy')
  • 문제 2: 감독별 평균 영화 평점 계산
    • 문제 설명: 각 영화 감독별로 그들의 영화 평점의 평균을 계산하고 싶습니다. 이를 통해 어떤 감독이 가장 높은 평균 평점을 가지고 있는지 알아볼 수 있습니다.
    • 쿼리 작성 목표: 모든 영화 감독의 영화 평점 평균을 계산하고, 평균 평점이 높은 순으로 정렬하는 MongoDB 쿼리를 함수로 만들어 문제를 해결해 봅니다. 
    • 각 감독의 영화 평점 평균을 계산하고, 이를 평균 평점이 높은 순으로 출력하는 쿼리입니다.
def calculate_average_ratings(db):
    movies_collection = db.movies
    pipeline = [
        {"$group": {"_id": "$director", "average_rating": {"$avg": "$rating"}}},
        {"$sort": {"average_rating": -1}},
        {"$project": {"_id": 0, "director": "$_id", "average_rating": 1}}
    ]
    results = movies_collection.aggregate(pipeline)
    for result in results:
        print(f"Director: {result['director']}, Average Rating: {result['average_rating']}")
  • 문제 3: 특정 사용자의 최근 행동 조회
    • 문제 설명: 특정 사용자의 최근 행동 로그를 조회하고자 합니다. 이 때, 최신 순으로 정렬하여 최근 5개의 행동만을 보고 싶습니다.
    • 쿼리 작성 목표: 사용자 ID가 1인 사용자의 최근 행동 5개를 시간 순으로 정렬하여 조회하는 MongoDB 쿼리를 함수로 만들어 문제를 해결해 봅니다. 
    • 특정 사용자의 최근 5개 행동을 시간 순으로 조회하는 쿼리입니다.
def find_recent_actions_by_user(db, user_id, limit=5):
    user_actions_collection = db.user_actions
    query = {"user_id": user_id}
    sort_criteria = {"timestamp": -1}

    actions = user_actions_collection.find(query).sort(sort_criteria).limit(limit)
    for action in actions:
        print(action)
  • 문제 4: 출판 연도별 책의 수 계산
    • 문제 설명 : 데이터베이스에 저장된 책 데이터를 이용하여 각 출판 연도별로 출판된 책의 수를 계산하고자 합니다. 이 데이터는 시간에 따른 출판 트렌드를 분석하는 데 사용될 수 있습니다.
    • 쿼리 작성 목표 : 각 출판 연도별로 출판된 책의 수를 계산하고, 출판된 책의 수가 많은 순서대로 정렬하는 MongoDB 쿼리를 함수로 만들어 문제를 해결해 봅니다. 
    • 각 출판 연도별로 출판된 책의 수를 계산하는 쿼리입니다.
def count_books_by_year(db):
    books_collection = db.books
    pipeline = [
        {"$group": {"_id": "$year", "count": {"$sum": 1}}},
        {"$sort": {"count": -1}},
        {"$project": {"_id": 0, "year": "$_id", "count": 1}}
    ]
    results = books_collection.aggregate(pipeline)
    for result in results:
        print(f"Year: {result['year']}, Book Count: {result['count']}")
 
  • 문제 5: 특정 사용자의 행동 유형 업데이트
    • 문제 설명: 특정 사용자의 행동 로그 중, 특정 날짜 이전의 "view" 행동을 "seen"으로 변경하고 싶습니다. 예를 들어, 사용자 ID가 1인 사용자의 2023년 4월 13일 이전의 모든 "view" 행동을 "seen"으로 변경하는 작업입니다.
    • 쿼리 작성 목표: 사용자 ID가 1인 사용자의 2023년 4월 13일 이전의 "view" 행동을 "seen"으로 변경하는 MongoDB 업데이트 쿼리를 함수로 만들어 문제를 해결해 봅니다. 
    • 특정 날짜 이전의 "view" 행동을 "seen"으로 변경하는 쿼리입니다.
from datetime import datetime

def update_user_actions_before_date(db, user_id, date, old_action, new_action):
    user_actions_collection = db.user_actions
    query = {"user_id": user_id, "action": old_action, "timestamp": {"$lt": date}}
    update = {"$set": {"action": new_action}}

    result = user_actions_collection.update_many(query, update)
    print(f"Updated {result.modified_count} documents.")

🧪 실전 사례

실제 데이터베이스에서 다양한 상황에 맞는 쿼리를 작성하는 과정에서, 각 쿼리의 결과를 통해 데이터 분석 및 관리 업무를 효율적으로 처리할 수 있습니다. 예를 들어, 영화 감독의 평균 평점을 계산하거나, 특정 장르의 책을 조회하는 등 다양한 분석이 가능합니다.


🧠 고급 팁 or 자주 하는 실수

  • 집계(aggregation) 파이프라인에서는 group, sort, project 단계를 순차적으로 실행하여 필요한 데이터를 가공하고, 원하는 형태로 출력할 수 있습니다.
  • 대량의 데이터 처리 시 update_many, insert_many를 사용하여 여러 문서를 한 번에 처리할 수 있습니다. 이때 성능이 중요한 경우, 인덱스를 잘 활용하는 것이 중요합니다.
  • 쿼리 성능 최적화를 위해 인덱스를 설정하고, 자주 사용하는 쿼리의 성능을 점검해야 합니다.

마무리 요약 및 복습 포인트

  1. MongoDB에서 데이터를 삽입, 조회, 업데이트하는 방법을 익혔습니다.
  2. 다양한 문제에 대해 쿼리를 작성하여 실전 예제를 경험했습니다.
  3. 집계 기능을 활용하여 복잡한 데이터 분석도 가능합니다.
  4. 효율적인 데이터 관리를 위해 인덱스를 고려하고 성능을 최적화하는 것이 중요합니다.