【springboot 技术代码】集成mongodb 详细步骤

SpringBoot 深度集成 MongoDB 详细步骤

    • 1. MongoDB 简介与 SpringBoot 集成概述
      • 1.1 SpringBoot 集成 MongoDB 的优势
    • 2. 环境准备与依赖配置
      • 2.1 版本兼容性矩阵
      • 2.2 详细依赖配置
      • 2.3 详细配置说明
        • 2.3.1 单节点配置
        • 2.3.2 集群配置
    • 3. 实体映射与集合管理
      • 3.1 详细实体类注解
      • 3.2 索引管理
    • 4. 数据操作详解
      • 4.1 Repository 接口扩展
      • 4.2 MongoTemplate 高级操作
        • 4.2.1 CRUD 操作
        • 4.2.2 复杂查询构建
        • 4.2.3 聚合操作
    • 5. 高级特性与最佳实践
      • 5.1 事务管理
      • 5.2 变更流(Change Streams)
      • 5.3 GridFS 文件存储
      • 5.4 性能优化策略
    • 6. 实战案例:电商平台商品管理系统
      • 6.1 系统架构设计
      • 6.2 核心功能实现
        • 6.2.1 商品服务
        • 6.2.2 商品评价服务
    • 7. 测试策略
      • 7.1 单元测试
      • 7.2 集成测试
    • 8. 常见问题与解决方案
      • 8.1 连接问题排查
      • 8.2 性能问题排查
      • 8.3 数据一致性问题
    • 9. 未来发展与扩展
      • 9.1 分片集群扩展
      • 9.2 时间序列集合(MongoDB 5.0+)
      • 9.3 与 Atlas Search 集成
    • 10. 总结

1. MongoDB 简介与 SpringBoot 集成概述

MongoDB 是一个基于分布式文件存储的开源 NoSQL 数据库系统,采用文档存储格式(BSON,类似 JSON)。与传统关系型数据库相比,MongoDB 具有以下特点:

  1. 无模式设计:集合中的文档可以有不同的结构
  2. 水平扩展:通过分片实现数据分布式存储
  3. 高性能:内存映射文件技术提高 I/O 效率
  4. 丰富的查询语言:支持丰富的查询表达式和索引类型
  5. 聚合框架:强大的数据分析能力

1.1 SpringBoot 集成 MongoDB 的优势

  1. 自动配置:SpringBoot 自动配置 MongoDB 客户端连接
  2. Repository 抽象:类似 JPA 的操作方式,降低学习曲线
  3. 对象映射:自动将 Java 对象与 MongoDB 文档相互转换
  4. 事务支持:支持多文档 ACID 事务(MongoDB 4.0+)
  5. 与 Spring 生态无缝集成:可与 Spring Data、Spring Security 等协同工作

2. 环境准备与依赖配置

2.1 版本兼容性矩阵

SpringBoot 版本Spring Data MongoDB 版本MongoDB 驱动版本MongoDB 服务器版本
2.7.x3.4.x4.4.x4.4-5.0
3.0.x4.0.x4.8.x5.0-6.0
3.1.x4.1.x4.9.x6.0+

2.2 详细依赖配置

<!-- pom.xml -->
<dependencies><!-- SpringBoot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Data MongoDB --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency><!-- 响应式支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb-reactive</artifactId></dependency><!-- 工具类 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- 测试 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- MongoDB 嵌入式测试 --><dependency><groupId>de.flapdoodle.embed</groupId><artifactId>de.flapdoodle.embed.mongo</artifactId><scope>test</scope></dependency>
</dependencies>

2.3 详细配置说明

2.3.1 单节点配置
# application.yml
spring:data:mongodb:host: localhostport: 27017database: mydbusername: myuserpassword: mypasswordauthentication-database: admin  # 认证数据库# 连接池配置auto-index-creation: truegridfs:database: mygridfs  # GridFS 存储的数据库
2.3.2 集群配置
spring:data:mongodb:uri: mongodb://user:password@host1:27017,host2:27017,host3:27017/mydb?replicaSet=myReplicaSet&authSource=admin# 高级连接配置option:min-connection-per-host: 10max-connection-per-host: 100max-wait-time: 120000connect-timeout: 5000socket-timeout: 60000server-selection-timeout: 30000

3. 实体映射与集合管理

3.1 详细实体类注解

import org.springframework.data.annotation.*;
import org.springframework.data.mongodb.core.index.*;
import org.springframework.data.mongodb.core.mapping.*;@Document(collection = "products")  // 指定集合名称
@CompoundIndex(def = "{'name': 1, 'category': 1}", name = "name_category_idx")
public class Product {@Idprivate String id;@Indexed(unique = true, direction = IndexDirection.ASCENDING)private String sku;@Field("product_name")  // 自定义字段名@TextIndexed(weight = 2)private String name;@TextIndexedprivate String description;@Indexed(direction = IndexDirection.DESCENDING)private Double price;@Indexedprivate String category;@CreatedDateprivate Date createTime;@LastModifiedDateprivate Date updateTime;@Versionprivate Long version;@DBRefprivate List<Review> reviews;@Transient  // 不持久化到数据库private Double discountPrice;// 嵌套文档private Manufacturer manufacturer;// 数组private List<String> tags;// 地理空间数据@GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)private double[] location;// 省略 getter/setter
}// 嵌套文档类
public class Manufacturer {private String name;private String address;private String contact;
}// 引用文档类
@Document(collection = "reviews")
public class Review {@Idprivate String id;private String content;private Integer rating;private Date createTime;
}

3.2 索引管理

import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.data.mongodb.core.index.IndexInfo;@Service
public class IndexManagementService {@Autowiredprivate MongoTemplate mongoTemplate;// 创建索引public String createIndex(Class<?> entityClass, String field, IndexDirection direction) {IndexOperations indexOps = mongoTemplate.indexOps(entityClass);Index index = new Index().on(field, direction);return indexOps.ensureIndex(index);}// 创建复合索引public String createCompoundIndex(Class<?> entityClass, String... fields) {IndexOperations indexOps = mongoTemplate.indexOps(entityClass);IndexDefinition indexDef = new CompoundIndexDefinition(new Document().append(fields[0], 1).append(fields[1], 1));return indexOps.ensureIndex(indexDef);}// 创建文本索引public String createTextIndex(Class<?> entityClass, String... fields) {IndexOperations indexOps = mongoTemplate.indexOps(entityClass);IndexDefinition indexDef = new TextIndexDefinitionBuilder().onFields(fields).withDefaultLanguage("english").withLanguageOverride("language").build();return indexOps.ensureIndex(indexDef);}// 获取所有索引public List<IndexInfo> getIndexes(Class<?> entityClass) {IndexOperations indexOps = mongoTemplate.indexOps(entityClass);return indexOps.getIndexInfo();}// 删除索引public void dropIndex(Class<?> entityClass, String indexName) {IndexOperations indexOps = mongoTemplate.indexOps(entityClass);indexOps.dropIndex(indexName);}
}

4. 数据操作详解

4.1 Repository 接口扩展

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.*;public interface ProductRepository extends MongoRepository<Product, String> {// 基本查询List<Product> findByName(String name);Product findBySku(String sku);List<Product> findByPriceBetween(Double minPrice, Double maxPrice);List<Product> findByCategoryOrderByPriceDesc(String category);// 分页查询Page<Product> findByCategory(String category, Pageable pageable);// 使用 @Query 注解@Query("{'name': ?0}")List<Product> findByNameCustom(String name);@Query("{'price': {$gt: ?0, $lt: ?1}}")List<Product> findByPriceRange(Double minPrice, Double maxPrice);// 使用正则表达式List<Product> findByNameLike(String namePattern);// 使用 SpEL 表达式@Query("{'$where': 'this.price > ?0'}")List<Product> findByPriceGreaterThan(Double price);// 多条件查询List<Product> findByNameAndCategory(String name, String category);// 使用聚合@Aggregation(pipeline = {"{$match: {category: ?0}}","{$group: {_id: '$manufacturer.name', avgPrice: {$avg: '$price'}}}"})List<AveragePriceByManufacturer> averagePriceByManufacturer(String category);// 文本搜索@TextScoreList<Product> findByDescriptionContaining(String text, Pageable pageable);// 地理空间查询List<Product> findByLocationNear(Point point, Distance distance);// 使用 exists 查询List<Product> findByManufacturerExists(boolean exists);// 使用注解定义索引@Meta(maxScanDocuments = 1000)List<Product> findByTagsIn(List<String> tags);
}// 聚合结果投影接口
public interface AveragePriceByManufacturer {String getManufacturerName();Double getAvgPrice();
}

4.2 MongoTemplate 高级操作

4.2.1 CRUD 操作
@Service
public class ProductService {@Autowiredprivate MongoTemplate mongoTemplate;// 插入文档public Product saveProduct(Product product) {return mongoTemplate.save(product);}// 批量插入public List<Product> saveAllProducts(List<Product> products) {return mongoTemplate.insertAll(products);}// 查询单个文档public Product findById(String id) {return mongoTemplate.findById(id, Product.class);}// 条件查询public List<Product> findExpensiveProducts(Double minPrice) {Query query = new Query(Criteria.where("price").gt(minPrice));return mongoTemplate.find(query, Product.class);}// 更新文档public UpdateResult updateProductPrice(String id, Double newPrice) {Query query = new Query(Criteria.where("id").is(id));Update update = new Update().set("price", newPrice).currentDate("updateTime");return mongoTemplate.updateFirst(query, update, Product.class);}// 删除文档public DeleteResult deleteProduct(String id) {Query query = new Query(Criteria.where("id").is(id));return mongoTemplate.remove(query, Product.class);}
}
4.2.2 复杂查询构建
public List<Product> complexProductSearch(ProductSearchCriteria criteria) {Criteria criteriaChain = new Criteria();// 关键词查询if (StringUtils.isNotBlank(criteria.getKeyword())) {TextCriteria textCriteria = TextCriteria.forDefaultLanguage().matchingAny(criteria.getKeyword()).caseSensitive(false);criteriaChain.andOperator(textCriteria);}// 分类过滤if (CollectionUtils.isNotEmpty(criteria.getCategories())) {criteriaChain.and("category").in(criteria.getCategories());}// 价格范围if (criteria.getMinPrice() != null || criteria.getMaxPrice() != null) {Criteria priceCriteria = new Criteria("price");if (criteria.getMinPrice() != null) {priceCriteria.gte(criteria.getMinPrice());}if (criteria.getMaxPrice() != null) {priceCriteria.lte(criteria.getMaxPrice());}criteriaChain.andOperator(priceCriteria);}// 标签查询if (CollectionUtils.isNotEmpty(criteria.getTags())) {criteriaChain.and("tags").all(criteria.getTags());}// 地理位置查询if (criteria.getLatitude() != null && criteria.getLongitude() != null) {Point point = new Point(criteria.getLongitude(), criteria.getLatitude());criteriaChain.and("location").nearSphere(point).maxDistance(criteria.getDistanceInKilometers() / 111.12); // 转换为弧度}Query query = new Query(criteriaChain);// 排序if (StringUtils.isNotBlank(criteria.getSortBy())) {Sort.Direction direction = criteria.isAscending() ? Sort.Direction.ASC : Sort.Direction.DESC;query.with(Sort.by(direction, criteria.getSortBy()));}// 分页if (criteria.getPage() != null && criteria.getSize() != null) {query.with(PageRequest.of(criteria.getPage(), criteria.getSize()));}// 字段投影if (CollectionUtils.isNotEmpty(criteria.getFieldsToInclude())) {Fields fields = Fields.fields();criteria.getFieldsToInclude().forEach(fields::include);query.fields(fields);}return mongoTemplate.find(query, Product.class);
}
4.2.3 聚合操作
public List<CategoryStats> getCategoryStatistics() {Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(Criteria.where("price").gt(0)),  // 过滤条件Aggregation.group("category")  // 按分类分组.avg("price").as("avgPrice")  // 计算平均价格.sum("price").as("totalRevenue")  // 计算总收入.count().as("productCount"),  // 计算产品数量Aggregation.project()  // 投影.and("_id").as("category").and("avgPrice").as("avgPrice").and("totalRevenue").as("totalRevenue").and("productCount").as("productCount"),Aggregation.sort(Sort.Direction.DESC, "totalRevenue"),  // 按总收入降序排序Aggregation.limit(10)  // 限制返回结果数);AggregationResults<CategoryStats> results = mongoTemplate.aggregate(aggregation, "products", CategoryStats.class);return results.getMappedResults();
}// 聚合结果类
@Data
public static class CategoryStats {private String category;private Double avgPrice;private Double totalRevenue;private Long productCount;
}

5. 高级特性与最佳实践

5.1 事务管理

@Service
public class OrderService {@Autowiredprivate MongoTemplate mongoTemplate;@Autowiredprivate ProductRepository productRepository;@Transactionalpublic Order createOrder(Order order) {// 检查并扣减库存for (OrderItem item : order.getItems()) {Product product = productRepository.findById(item.getProductId()).orElseThrow(() -> new RuntimeException("Product not found"));if (product.getStock() < item.getQuantity()) {throw new RuntimeException("Insufficient stock");}product.setStock(product.getStock() - item.getQuantity());productRepository.save(product);}// 保存订单return mongoTemplate.save(order);}// 配置事务管理器@Beanpublic MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {return new MongoTransactionManager(dbFactory);}
}

5.2 变更流(Change Streams)

@Service
public class ProductChangeListener {@Autowiredprivate MongoTemplate mongoTemplate;@PostConstructpublic void watchProductChanges() {new Thread(() -> {List<Bson> pipeline = Arrays.asList(Aggregates.match(Filters.in("operationType", Arrays.asList("insert", "update", "delete"))));MongoCollection<Document> collection = mongoTemplate.getCollection("products");ChangeStreamIterable<Document> changeStream = collection.watch(pipeline).fullDocument(FullDocument.UPDATE_LOOKUP);changeStream.forEach(event -> {String operationType = event.getOperationType().getValue();Document fullDocument = event.getFullDocument();switch (operationType) {case "insert":handleInsert(fullDocument);break;case "update":handleUpdate(event.getDocumentKey(), fullDocument);break;case "delete":handleDelete(event.getDocumentKey());break;}});}).start();}private void handleInsert(Document productDoc) {System.out.println("New product added: " + productDoc.toJson());}private void handleUpdate(Bson documentKey, Document fullDocument) {System.out.println("Product updated: " + documentKey + ", new data: " + fullDocument.toJson());}private void handleDelete(Bson documentKey) {System.out.println("Product deleted: " + documentKey);}
}

5.3 GridFS 文件存储

@Service
public class FileStorageService {@Autowiredprivate GridFsTemplate gridFsTemplate;public String storeFile(InputStream inputStream, String filename, String contentType) {ObjectId fileId = gridFsTemplate.store(inputStream, filename, contentType);return fileId.toString();}public GridFSDBFile getFile(String fileId) {return gridFsTemplate.findOne(new Query(Criteria.where("_id").is(fileId)));}public void deleteFile(String fileId) {gridFsTemplate.delete(new Query(Criteria.where("_id").is(fileId)));}public List<GridFSFile> listFiles() {return gridFsTemplate.find(new Query()).into(new ArrayList<>());}
}

5.4 性能优化策略

  1. 索引优化:
    • 为常用查询字段创建适当索引
    • 使用复合索引优化多字段查询
    • 定期分析查询性能并调整索引
  2. 查询优化:
    • 使用投影只返回必要字段
    • 限制返回文档数量
    • 避免使用 $where 和 JavaScript 表达式
    • 使用 covered queries(查询完全由索引满足)
  3. 批量操作:
    • 使用 bulkWrite 进行批量插入/更新
    • 批量操作时适当设置 ordered 参数
  4. 读写分离:
    • 配置从节点读取
@Bean
public MongoClient mongoClient() {ConnectionString connectionString = new ConnectionString("mongodb://host1:27017,host2:27017,host3:27017/mydb?readPreference=secondaryPreferred");return MongoClients.create(connectionString);
}
  1. 分片集群:
    • 对于大数据集,配置分片集群
    • 选择合适的分片键

6. 实战案例:电商平台商品管理系统

6.1 系统架构设计

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  前端应用/API   │───▶│  SpringBoot应用  │───▶│ MongoDB集群      │
└─────────────────┘    └─────────────────┘    └─────────────────┘▲                      ▲                      ▲│                      │                      │
┌──────┴───────┐    ┌─────────┴─────────┐    ┌──────┴───────┐
│  缓存(Redis)  │    │  消息队列(Kafka)    │    │  文件存储(S3)  │
└──────────────┘    └───────────────────┘    └───────────────┘

6.2 核心功能实现

6.2.1 商品服务
@Service
public class ProductServiceImpl implements ProductService {@Autowiredprivate ProductRepository productRepository;@Autowiredprivate MongoTemplate mongoTemplate;@Autowiredprivate RedisTemplate<String, Object> redisTemplate;private static final String PRODUCT_CACHE_PREFIX = "product:";@Overridepublic Product createProduct(Product product) {// 验证SKU唯一性if (productRepository.findBySku(product.getSku()) != null) {throw new RuntimeException("SKU already exists");}// 设置创建时间product.setCreateTime(new Date());product.setUpdateTime(new Date());// 保存到数据库Product savedProduct = productRepository.save(product);// 清除相关缓存redisTemplate.delete(PRODUCT_CACHE_PREFIX + savedProduct.getId());redisTemplate.delete("products:category:" + savedProduct.getCategory());return savedProduct;}@Overridepublic Product getProductById(String id) {// 先尝试从缓存获取Product cachedProduct = (Product) redisTemplate.opsForValue().get(PRODUCT_CACHE_PREFIX + id);if (cachedProduct != null) {return cachedProduct;}// 从数据库查询Product product = productRepository.findById(id).orElseThrow(() -> new RuntimeException("Product not found"));// 存入缓存redisTemplate.opsForValue().set(PRODUCT_CACHE_PREFIX + id, product, 30, TimeUnit.MINUTES);return product;}@Overridepublic Page<Product> searchProducts(ProductSearchRequest request) {// 构建查询条件Criteria criteria = new Criteria();if (StringUtils.isNotBlank(request.getKeyword())) {criteria.orOperator(Criteria.where("name").regex(request.getKeyword(), "i"),Criteria.where("description").regex(request.getKeyword(), "i"));}if (StringUtils.isNotBlank(request.getCategory())) {criteria.and("category").is(request.getCategory());}if (request.getMinPrice() != null && request.getMaxPrice() != null) {criteria.and("price").gte(request.getMinPrice()).lte(request.getMaxPrice());}Query query = new Query(criteria);// 分页和排序Pageable pageable = PageRequest.of(request.getPage(), request.getSize(), Sort.by(Sort.Direction.fromString(request.getSortDirection()), request.getSortBy()));query.with(pageable);// 执行查询long count = mongoTemplate.count(query, Product.class);List<Product> products = mongoTemplate.find(query, Product.class);return new PageImpl<>(products, pageable, count);}@Override@Transactionalpublic void updateProductStock(String productId, int quantityChange) {// 使用原子操作更新库存Query query = new Query(Criteria.where("id").is(productId));Update update = new Update().inc("stock", quantityChange).currentDate("updateTime");UpdateResult result = mongoTemplate.updateFirst(query, update, Product.class);if (result.getMatchedCount() == 0) {throw new RuntimeException("Product not found");}// 清除缓存redisTemplate.delete(PRODUCT_CACHE_PREFIX + productId);}@Overridepublic List<CategoryStats> getCategoryStatistics() {// 使用聚合框架统计分类数据Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(Criteria.where("status").is("ACTIVE")),Aggregation.group("category").avg("price").as("avgPrice").sum("stock").as("totalStock").count().as("productCount"),Aggregation.sort(Sort.Direction.DESC, "productCount"));AggregationResults<CategoryStats> results = mongoTemplate.aggregate(aggregation, Product.class, CategoryStats.class);return results.getMappedResults();}
}
6.2.2 商品评价服务
@Service
public class ReviewServiceImpl implements ReviewService {@Autowiredprivate ReviewRepository reviewRepository;@Autowiredprivate MongoTemplate mongoTemplate;@Overridepublic Review addReview(Review review) {// 验证产品是否存在if (!mongoTemplate.exists(new Query(Criteria.where("id").is(review.getProductId())), Product.class)) {throw new RuntimeException("Product not found");}// 设置创建时间review.setCreateTime(new Date());// 保存评价Review savedReview = reviewRepository.save(review);// 更新产品的平均评分updateProductRating(review.getProductId());return savedReview;}private void updateProductRating(String productId) {// 使用聚合框架计算平均评分Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(Criteria.where("productId").is(productId)),Aggregation.group().avg("rating").as("avgRating"));AggregationResults<AverageRating> results = mongoTemplate.aggregate(aggregation, Review.class, AverageRating.class);Double avgRating = results.getMappedResults().isEmpty() ? 0.0 : results.getMappedResults().get(0).getAvgRating();// 更新产品评分Query query = new Query(Criteria.where("id").is(productId));Update update = new Update().set("averageRating", avgRating).currentDate("updateTime");mongoTemplate.updateFirst(query, update, Product.class);}@Overridepublic Page<Review> getProductReviews(String productId, Pageable pageable) {return reviewRepository.findByProductId(productId, pageable);}@Overridepublic List<RatingDistribution> getRatingDistribution(String productId) {Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(Criteria.where("productId").is(productId)),Aggregation.group("rating").count().as("count"),Aggregation.sort(Sort.Direction.ASC, "_id"));AggregationResults<RatingDistribution> results = mongoTemplate.aggregate(aggregation, Review.class, RatingDistribution.class);return results.getMappedResults();}// 聚合结果类private static class AverageRating {private Double avgRating;// getter/setter}private static class RatingDistribution {private Integer rating;private Long count;// getter/setter}
}

7. 测试策略

7.1 单元测试

@DataMongoTest
@ExtendWith(SpringExtension.class)
public class ProductRepositoryTest {@Autowiredprivate ProductRepository productRepository;@Autowiredprivate MongoTemplate mongoTemplate;@BeforeEachpublic void setup() {productRepository.deleteAll();// 初始化测试数据Product product1 = new Product();product1.setName("Laptop");product1.setCategory("Electronics");product1.setPrice(999.99);Product product2 = new Product();product2.setName("Smartphone");product2.setCategory("Electronics");product2.setPrice(699.99);productRepository.saveAll(Arrays.asList(product1, product2));}@Testpublic void testFindByCategory() {List<Product> electronics = productRepository.findByCategory("Electronics");assertEquals(2, electronics.size());}@Testpublic void testPriceRangeQuery() {List<Product> expensiveProducts = productRepository.findByPriceBetween(700.0, 1000.0);assertEquals(1, expensiveProducts.size());assertEquals("Laptop", expensiveProducts.get(0).getName());}
}

7.2 集成测试

@SpringBootTest
@Testcontainers
public class ProductServiceIntegrationTest {@Containerstatic MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:5.0");@DynamicPropertySourcestatic void setProperties(DynamicPropertyRegistry registry) {registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);}@Autowiredprivate ProductService productService;@Autowiredprivate ProductRepository productRepository;@Test@Transactionalpublic void testCreateAndRetrieveProduct() {Product product = new Product();product.setName("Test Product");product.setCategory("Test");product.setPrice(100.0);Product savedProduct = productService.createProduct(product);assertNotNull(savedProduct.getId());Product retrievedProduct = productService.getProductById(savedProduct.getId());assertEquals("Test Product", retrievedProduct.getName());}@Testpublic void testProductSearch() {ProductSearchRequest request = new ProductSearchRequest();request.setCategory("Electronics");request.setPage(0);request.setSize(10);Page<Product> result = productService.searchProducts(request);assertTrue(result.getTotalElements() > 0);}
}

8. 常见问题与解决方案

8.1 连接问题排查

问题现象:无法连接到 MongoDB 服务器
排查步骤:

  1. 检查连接字符串是否正确
  2. 验证网络连通性
  3. 检查认证信息
  4. 查看 MongoDB 服务器日志
// 测试连接
try {MongoClient client = MongoClients.create("mongodb://localhost:27017");client.listDatabaseNames().first();System.out.println("Connection successful");
} catch (Exception e) {System.err.println("Connection failed: " + e.getMessage());
}

8.2 性能问题排查

问题现象:查询响应慢
排查步骤:

  1. 使用 explain() 分析查询执行计划
Query query = new Query(Criteria.where("price").gt(100));
Document explain = mongoTemplate.getCollection("products").find(query.getQueryObject()).explain();
System.out.println(explain.toJson());
  1. 检查索引使用情况
  2. 分析 MongoDB 服务器资源使用情况
  3. 优化查询条件和索引

8.3 数据一致性问题

解决方案:

  1. 使用多文档事务(MongoDB 4.0+)
  2. 实现最终一致性模式
  3. 使用变更流监听数据变化
  4. 定期数据校验和修复

9. 未来发展与扩展

9.1 分片集群扩展

@Configuration
public class ShardingConfig {@Beanpublic MongoClient mongoClient() {// 配置分片集群连接ConnectionString connectionString = new ConnectionString("mongodb://shard1:27017,shard2:27017,shard3:27017/admin?replicaSet=shardRS");MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(connectionString).writeConcern(WriteConcern.MAJORITY).readPreference(ReadPreference.secondaryPreferred()).retryWrites(true).build();return MongoClients.create(settings);}
}

9.2 时间序列集合(MongoDB 5.0+)

@Document(collection = "sensor_readings")
@TimeSeries(collection = "sensor_readings", timeField = "timestamp", metaField = "sensorMetadata", granularity = TimeSeriesGranularity.SECONDS)
public class SensorReading {@Idprivate String id;private Date timestamp;private SensorMetadata sensorMetadata;private Double value;// getter/setter
}public class SensorMetadata {private String sensorId;private String location;private String type;
}

9.3 与 Atlas Search 集成

public List<Product> fullTextSearch(String query) {TextCriteria criteria = TextCriteria.forDefaultLanguage().matching(query).caseSensitive(false).diacriticSensitive(false);Query searchQuery = TextQuery.queryText(criteria).sortByScore().with(PageRequest.of(0, 10));return mongoTemplate.find(searchQuery, Product.class);
}

10. 总结

本文详细介绍了 SpringBoot 集成 MongoDB 的完整方案,涵盖以下内容:

  1. 环境准备:版本兼容性、依赖配置、连接设置
  2. 数据建模:实体映射、索引管理、关系处理
  3. 数据操作:基础CRUD、复杂查询、聚合框架
  4. 高级特性:事务管理、变更流、GridFS
  5. 性能优化:索引策略、查询优化、读写分离
  6. 实战案例:电商平台商品管理系统实现
  7. 测试策略:单元测试、集成测试方法
  8. 问题排查:连接问题、性能问题解决方案
  9. 未来扩展:分片集群、时间序列集合等
    通过本指南,您应该能够在 SpringBoot 项目中高效地集成 MongoDB,构建高性能、可扩展的应用程序,并根据业务需求进行定制化开发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/96697.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/96697.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算-K8s 运维:Python SDK 操作 Job/Deployment/Pod+RBAC 权限配置及自定义 Pod 调度器实战

简介 在 Kubernetes 运维中,自动化资源管理与定制化调度是提升效率的核心需求,而 Python SDK 是实现这一目标的关键工具。本次围绕 K8s Python SDK 展开全场景实战,以 “代码 + 效果” 双维度,覆盖 5 大核心运维场景,Job 自动化创建(先清理重名资源再部署计算任务)、De…

Excel 转化成JSON

Excel 转化成JSON import pandas as pd import json import osdef excel_to_json(excel_path, sheet_name0, orientrecords, save_pathNone):"""将Excel文件转换为JSON格式并可选择保存到文件参数:excel_path: Excel文件路径sheet_name: 工作表名称或索引&#…

Linux 进阶用法

一、系统性能调优系统性能调优是 Linux 管理中的关键技能&#xff0c;它能显著提升系统在不同应用场景下的表现。通过针对性的调优&#xff0c;可以解决资源瓶颈问题&#xff0c;提高服务响应速度&#xff0c;优化资源利用率。&#xff08;一&#xff09;CPU 性能调优知识点详解…

14.苹果ios逆向-app的调试方式

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;图灵Python学院 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取码&#xff1…

深入理解 React useEffect

一、useEffect基础概念 1、什么是副作用&#xff08;Side Effects&#xff09;&#xff1f; 在React中&#xff0c;副作用是指那些与组件渲染结果无关的操作&#xff0c;例如&#xff1a; 数据获取&#xff08;API调用&#xff09;手动修改DOM设置订阅或定时器记录日志 2、useE…

Yapi中通过MongoDB修改管理员密码与新增管理员

如何在Docker部署的Yapi中通过MongoDB修改管理员密码与新增管理员便捷管理Yapi权限&#xff1a;无需前端重置&#xff0c;直接通过数据库操作修改密码及添加管理员一、进入MongoDB容器并连接数据库 首先&#xff0c;通过以下命令进入运行中的MongoDB容器&#xff1a; docker ex…

【EasyR1】GRPO训练

官方github&#xff1a;https://github.com/hiyouga/EasyR1 参考&#xff1a;https://opendeep.wiki/hiyouga/EasyR1/quickstart 代码和环境配置 github&#xff1a;https://github.com/hiyouga/EasyR1 新建一个虚拟环境&#xff1a; python -m venv easyr1 source easyr1/b…

2025年KBS SCI1区TOP,新颖奖励与ε-贪婪衰减Q-learning算法+局部移动机器人路径规划,深度解析+性能实测

目录1.摘要2.新颖奖励与ε-贪婪衰减Q-learning算法3.结果展示4.参考文献5.代码获取6.算法辅导应用定制读者交流1.摘要 路径规划是移动机器人的核心任务&#xff0c;需要在高效导航的同时规避障碍。本文提出了一种改进Q-learning算法——定制化奖励与ε-贪婪衰减Q-learning&…

运行npm run命令报错“error:0308010C:digital envelope routines::unsupported”

下载的前后端分离架构的开源项目&#xff0c;运行“npm run serve”命令启动前端服务时报错“error:0308010C:digital envelope routines::unsupported”&#xff0c;这个错误通常是由于Node.js版本与项目依赖不兼容导致的&#xff0c;特别是在Node.js v17版本中&#xff0c;百…

AI计算提效关键。自适应弹性加速,基于存算架构做浮点运算

一、自适应弹性加速是提升芯片能效比的有力手段自适应弹性加速技术是现代芯片设计中提升能效比的关键路径之一。它摒弃了传统芯片在设计时采用的静态、固化的资源分配与功能设定模式&#xff0c;通过引入动态调整机制&#xff0c;使得芯片能够根据实时的应用需求和负载变化&…

Spring Boot测试陷阱:失败测试为何“传染”其他用例?

一个测试失败&#xff0c;为何“传染”其他测试&#xff1f;——Spring Boot 单元测试独立性与泛型陷阱实战解析 &#x1f6a9; 问题背景 在日常开发中&#xff0c;我们常会遇到这样的场景&#xff1a; 正在开发新功能 A&#xff0c;写了一个 testFeatureA() 测试方法&#xff…

Web开发中的CGI:通用网关接口详解

一、CGI的设计意图&#xff1a;解决Web的"静态"困境 在CGI出现之前&#xff0c;Web服务器只能做一件事&#xff1a;返回预先写好的静态文件&#xff08;HTML、图片等&#xff09;。每个用户看到的内容都是一模一样的。 设计意图很简单但却革命性&#xff1a; 让Web服…

在 SSMS 中查找和打开已保存的查询文件

在 SSMS 中查找和打开已保存的查询文件 在 SQL Server Management Studio (SSMS) 中&#xff0c;您可以轻松地查找并打开已保存的查询文件&#xff08;通常以 .sql 扩展名保存&#xff09;。SSMS 提供了直观的界面支持直接打开这些文件&#xff0c;无需额外工具。以下是详细步骤…

Protues使用说明及Protues与Keil联合仿真实现点亮小灯和流水灯

目录 1Protues介绍及新建工程 1.1进入软件 1.2文件创建 1.3默认选项 1.5设计面板 1.6添加元器件 1.7终端模式 1.8激励源模式 1.9探针模式 1.10仪表 1.11二维直线 1.12字符 2 Protues电路原理图仿真 2.1 220V交流电转5V直流电稳压电路仿真原理图 2.1.1 仿真原理图…

Linux PCI 子系统:工作原理与实现机制深度分析

Linux PCI 子系统&#xff1a;工作原理与实现机制深度分析 1. Linux PCI 子系统基础概念 1.1 PCI/PCIe 基础概念回顾 总线拓扑&#xff1a; PCI/PCIe 系统是一个树形结构。CPU 连接到 Root Complex (RC)&#xff0c;RC 连接至 PCIe 交换机 (Switch) 和 PCIe 端点设备 (Endpoint…

RabbitMQ 全面指南:架构解析与案例实战

目录一、RabbitMQ 简介1.1 什么是 RabbitMQ1.2 RabbitMQ 的核心组件1.3 RabbitMQ 的应用场景二、环境搭建2.1 安装 RabbitMQ2.2 安装 Erlang2.3 配置 RabbitMQ三、RabbitMQ 核心概念与工作原理3.1 消息模型3.2 交换机类型3.3 队列特性3.4 消息确认机制四、Spring Boot 集成 Rab…

6.2 el-menu

一、 <el-menu>: 菜单组件&#xff0c;定义了侧边栏内部的具体导航项、层级结构和交互行为。<el-container><!-- 侧边栏容器 --><el-aside width"200px"><!-- 菜单内容 --><el-menu default-active"1" class"el-men…

Windows 笔记本实现仅关屏仍工作:一种更便捷的 “伪熄屏” 方案

在使用 Windows 笔记本作为临时服务器或需要后台持续运行程序时&#xff0c;我们常面临一个需求&#xff1a;关闭屏幕以节省电量或减少光污染&#xff0c;同时保持系统正常工作。然而&#xff0c;网络上流传的诸多方法往往存在局限&#xff0c;要么无法兼顾 “熄屏” 与 “工作…

Linux应急响应一般思路(二)

进程排查进程(Process)是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;是操作系统结构的基础无论是在Windows系统还是Linux系统中&#xff0c;主机在感染恶意程序后&#xff0c;恶意程序都会启动相应的进程&#x…

基于 SkyWalking + Elasticsearch + Grafana 的可落地调用链监控方案

这个方案成熟稳定、社区活跃、部署相对简单,非常适合中小型团队作为第一代调用链系统落地。 一、核心组件选型与角色 组件 版本建议 角色 优点 Apache SkyWalking v9.x+ 核心平台 (采集、分析、存储、UI) 国产优秀,Java Agent无侵入接入,功能全面,性能损耗低 Elasticsearc…