-
Notifications
You must be signed in to change notification settings - Fork 2
feat: crud functionality and aggregations for python backend #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a couple comments/questions. nice job!
| @router.get("/{id}", response_model=SuccessResponse[Movie]) | ||
| async def get_movie_by_id(id: str): | ||
| # Validate ObjectId format | ||
| object_id = ObjectId(id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we wrap this in a try-except? i.e. what happens if id isn't valid?
| # Use findOne() to get a single document by _id | ||
| movie = await db.movies.find_one({"_id": object_id}) | ||
|
|
||
| movie["_id"] = str(movie["_id"]) # Convert ObjectId to string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same - what happens if movie is None?
| print(f"Database name: {db.name if hasattr(db, 'name') else 'unknown'}") | ||
| print(f"Collection name: movies") | ||
|
|
||
| # For motor (async MongoDB driver), we need to await the aggregate call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we weren't using Motor (instead using PyMongo's native async)
| # For motor (async MongoDB driver), we need to await the aggregate call | |
| # For async PyMongo driver, we need to await the aggregate call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, we aren't using motor. Just async within the PyMongo driver.
|
|
||
| # For motor (async MongoDB driver), we need to await the aggregate call | ||
| cursor = await db.movies.aggregate(pipeline) | ||
| results = await cursor.to_list(length=None) # Convert cursor to list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want to point out why we're using to_list() for aggregations vs. async for for find queries (what you did in lines 105-108)
| cursor = await db.movies.aggregate(pipeline) | ||
| results = await cursor.to_list(length=None) # Convert cursor to list | ||
|
|
||
| print(f"Aggregation returned {len(results)} results") # Debug logging |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a ticket to add proper logging?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job!
These are some minor changes. Mostly to keep the code similar and adding in validation. I didn't get to the end of the file. I will get to find and delete on Monday.
I havent written an aggregation yet, so I might leave those for now. I will ping you, if I get to them.
| object_id = ObjectId(id) | ||
|
|
||
| # Use findOne() to get a single document by _id | ||
| movie = await db.movies.find_one({"_id": object_id}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To grab the db, I added a function called get_collection from mongo_client.py file to make unit testing easier later. I am calling the db like this in the rest of the functions:
movies_collection = get_collection("movies")
| genre (str): The genre of the movie. | ||
| year (int): The year the movie was released. | ||
| min_rating (float): The minimum IMDB rating. | ||
| max_rating (float): The maximum IMDB rating. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The request body for this the CreateMovieRequest object.
| result = await db.movies.insert_one(movie_data) | ||
|
|
||
| # Retrieve the created document to return complete data | ||
| created_movie = await db.movies.find_one({"_id": result.inserted_id}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to verify that the document was created before querying it. A check that result is acknowledged.
| SuccessResponse[Movie]: A response object containing the created movie data. | ||
| """ | ||
|
|
||
| @router.post("/", response_model=SuccessResponse[CreateMovieRequest], status_code=201) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be:
response_model=SuccessResponse[Movie]
We are returning the movie
|
|
||
| @router.delete("/{id}", response_model=SuccessResponse[dict]) | ||
| async def delete_movie_by_id(id: str): | ||
| object_id = ObjectId(id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap in a try/catch. Id might not be valid.
| result = await db.movies.delete_one({"_id": object_id}) | ||
|
|
||
| if result.deleted_count == 0: | ||
| raise HTTPException(status_code=404, detail="Movie not found") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets use the create_error_response() to keep the errors consistent.
| object_id = ObjectId(id) | ||
|
|
||
| # Use deleteOne() to remove a single document | ||
| result = await db.movies.delete_one({"_id": object_id}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as above about accessing the db.
Basic crud functionality and aggregation pipelines for python backend
This PR introduces basic CRUD functionality and aggregation pipelines for the FastAPI application. It sets up find, insert, delete, and find and delete operations. It also adds aggregations for movies by genre, by year, most recent comments (joining the movies collection with the comments collection), and by director.
Key Changes
Testing