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
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());