From 0ddb4a1a179faedc2e4c70ed32b356eadb3317cf Mon Sep 17 00:00:00 2001 From: cbullinger Date: Wed, 5 Nov 2025 11:17:27 -0500 Subject: [PATCH 1/2] fix(java): index creation logic --- .../config/DatabaseVerification.java | 111 ++++++++++++------ 1 file changed, 73 insertions(+), 38 deletions(-) diff --git a/server/java-spring/src/main/java/com/mongodb/samplemflix/config/DatabaseVerification.java b/server/java-spring/src/main/java/com/mongodb/samplemflix/config/DatabaseVerification.java index cb3368f..752168f 100644 --- a/server/java-spring/src/main/java/com/mongodb/samplemflix/config/DatabaseVerification.java +++ b/server/java-spring/src/main/java/com/mongodb/samplemflix/config/DatabaseVerification.java @@ -132,32 +132,43 @@ private void verifyMoviesCollection() { * these fields, which is used by the search endpoint in the API. * *

The index is created in the background to avoid blocking other operations. - * If the index already exists, MongoDB will ignore the duplicate creation request. + * If the index already exists, this method will detect it and skip creation. * * @param moviesCollection the movies collection to create the index on */ private void createTextSearchIndex(MongoCollection moviesCollection) { try { - // Create compound text index on plot, title, and fullplot fields - // The background option allows the index to be built without blocking other operations - IndexOptions indexOptions = new IndexOptions() - .name(TEXT_INDEX_NAME) - .background(true); - - // Create the text index using field name constants from Movie.Fields - // This makes the coupling between Movie class and index creation explicit - // and allows IDE "Find Usages" to track dependencies - // MongoDB will automatically ignore this if the index already exists - moviesCollection.createIndex( - Indexes.compoundIndex( - Indexes.text(Movie.Fields.PLOT), - Indexes.text(Movie.Fields.TITLE), - Indexes.text(Movie.Fields.FULLPLOT) - ), - indexOptions - ); + // Check if the text search index already exists + boolean indexExists = false; + for (Document index : moviesCollection.listIndexes()) { + if (TEXT_INDEX_NAME.equals(index.getString("name"))) { + indexExists = true; + logger.info("Text search index '{}' already exists", TEXT_INDEX_NAME); + break; + } + } - logger.info("Text search index '{}' created/verified for movies collection", TEXT_INDEX_NAME); + if (!indexExists) { + // Create compound text index on plot, title, and fullplot fields + // The background option allows the index to be built without blocking other operations + IndexOptions indexOptions = new IndexOptions() + .name(TEXT_INDEX_NAME) + .background(true); + + // Create the text index using field name constants from Movie.Fields + // This makes the coupling between Movie class and index creation explicit + // and allows IDE "Find Usages" to track dependencies + moviesCollection.createIndex( + Indexes.compoundIndex( + Indexes.text(Movie.Fields.PLOT), + Indexes.text(Movie.Fields.TITLE), + Indexes.text(Movie.Fields.FULLPLOT) + ), + indexOptions + ); + + logger.info("Text search index '{}' created successfully for movies collection", TEXT_INDEX_NAME); + } } catch (Exception e) { // Log error but don't fail - the application can still function without the index @@ -240,7 +251,7 @@ private void createMongoDBSearchIndex(MongoCollection moviesCollection } /** - * Creates an index on the year field for the movies collection. + * Creates an index on the year field for the movies collection if it doesn't already exist. * *

This index improves performance for aggregation queries that filter by year, * such as the movies with comments aggregation. @@ -249,16 +260,28 @@ private void createMongoDBSearchIndex(MongoCollection moviesCollection */ private void createYearIndex(MongoCollection moviesCollection) { try { - IndexOptions indexOptions = new IndexOptions() - .name(YEAR_INDEX_NAME) - .background(true); + // Check if the year index already exists + boolean indexExists = false; + for (Document index : moviesCollection.listIndexes()) { + if (YEAR_INDEX_NAME.equals(index.getString("name"))) { + indexExists = true; + logger.info("Year index '{}' already exists", YEAR_INDEX_NAME); + break; + } + } - moviesCollection.createIndex( - Indexes.ascending(Movie.Fields.YEAR), - indexOptions - ); + if (!indexExists) { + IndexOptions indexOptions = new IndexOptions() + .name(YEAR_INDEX_NAME) + .background(true); + + moviesCollection.createIndex( + Indexes.ascending(Movie.Fields.YEAR), + indexOptions + ); - logger.info("Year index '{}' created/verified for movies collection", YEAR_INDEX_NAME); + logger.info("Year index '{}' created successfully for movies collection", YEAR_INDEX_NAME); + } } catch (Exception e) { logger.error("Could not create year index: {}", e.getMessage()); @@ -291,7 +314,7 @@ private void verifyCommentsCollection() { } /** - * Creates an index on the movie_id field for the comments collection. + * Creates an index on the movie_id field for the comments collection if it doesn't already exist. * *

This index is critical for $lookup performance when joining movies with comments. * Without this index, the $lookup operation will perform a collection scan for each movie, @@ -301,16 +324,28 @@ private void verifyCommentsCollection() { */ private void createMovieIdIndex(MongoCollection commentsCollection) { try { - IndexOptions indexOptions = new IndexOptions() - .name(MOVIE_ID_INDEX_NAME) - .background(true); + // Check if the movie_id index already exists + boolean indexExists = false; + for (Document index : commentsCollection.listIndexes()) { + if (MOVIE_ID_INDEX_NAME.equals(index.getString("name"))) { + indexExists = true; + logger.info("Movie ID index '{}' already exists", MOVIE_ID_INDEX_NAME); + break; + } + } - commentsCollection.createIndex( - Indexes.ascending("movie_id"), - indexOptions - ); + if (!indexExists) { + IndexOptions indexOptions = new IndexOptions() + .name(MOVIE_ID_INDEX_NAME) + .background(true); - logger.info("Movie ID index '{}' created/verified for comments collection", MOVIE_ID_INDEX_NAME); + commentsCollection.createIndex( + Indexes.ascending("movie_id"), + indexOptions + ); + + logger.info("Movie ID index '{}' created successfully for comments collection", MOVIE_ID_INDEX_NAME); + } } catch (Exception e) { logger.error("Could not create movie_id index: {}", e.getMessage()); From 54eab015e14166afae5afa8072791a7333e8c687 Mon Sep 17 00:00:00 2001 From: cbullinger Date: Wed, 5 Nov 2025 11:25:35 -0500 Subject: [PATCH 2/2] docs(java): update README --- mflix/README-JAVA-SPRING.md | 38 ++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/mflix/README-JAVA-SPRING.md b/mflix/README-JAVA-SPRING.md index 17bf602..988fc49 100644 --- a/mflix/README-JAVA-SPRING.md +++ b/mflix/README-JAVA-SPRING.md @@ -18,8 +18,8 @@ This is a full-stack movie browsing application built with Java Spring Boot and - **Java 21** or higher - **Node.js 20** or higher -- **MongoDB Atlas account** with the `sample_mflix` dataset loaded - - [Load sample data](https://www.mongodb.com/docs/atlas/sample-data/) in your Atlas cluster +- **MongoDB Atlas cluster or local deployment** with the `sample_mflix` dataset loaded + - [Load sample data](https://www.mongodb.com/docs/atlas/sample-data/) - **Maven** (included via Maven Wrapper) ## Getting Started @@ -130,12 +130,40 @@ The Next.js frontend uses: - **Next.js 16** with App Router - **Turbopack** for fast development builds -To build for production: +#### Development Mode + +For active development with hot reloading and fast refresh: + +```bash +cd client +npm run dev +``` + +This starts the development server on `http://localhost:3000` with Turbopack for fast rebuilds. + +#### Production Build + +To create an optimized production build and run it: + +```bash +cd client +npm run build # Creates optimized production build +npm start # Starts production server +``` + +The production build: +- Minifies and optimizes JavaScript and CSS +- Optimizes images and assets +- Generates static pages where possible +- Provides better performance for end users + +#### Linting + +To check code quality: ```bash cd client -npm run build -npm start +npm run lint ``` ## Issues