SpringBoot3.x入门到精通系列:4.1 整合 MongoDB 详解
SpringBoot 3.x 整合 MongoDB 详解
🎯 MongoDB简介
MongoDB是一个基于分布式文件存储的NoSQL数据库,由C++语言编写。它是一个面向文档的数据库,具有高性能、高可用性和易扩展性的特点。
核心特性
- 文档存储: 使用BSON格式存储数据
- 动态模式: 无需预定义表结构
- 高性能: 支持索引和内存映射
- 高可用: 支持副本集和分片
- 水平扩展: 支持自动分片
- 丰富查询: 支持复杂查询和聚合操作
核心概念
- Database: 数据库,类似于关系型数据库的数据库
- Collection: 集合,类似于关系型数据库的表
- Document: 文档,类似于关系型数据库的行
- Field: 字段,类似于关系型数据库的列
- Index: 索引,提高查询性能
- Replica Set: 副本集,提供高可用性
- Sharding: 分片,提供水平扩展
🚀 快速开始
1. 添加依赖
<dependencies><!-- SpringBoot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- SpringBoot MongoDB Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency><!-- 数据验证 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency><!-- JSON处理 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
2. MongoDB配置
spring:# MongoDB配置data:mongodb:# MongoDB连接URIuri: mongodb://localhost:27017/demo_db# 或者分别配置# host: localhost# port: 27017# database: demo_db# username: admin# password: password# authentication-database: admin# 连接池配置options:# 最大连接数max-pool-size: 100# 最小连接数min-pool-size: 10# 连接超时时间connect-timeout: 10000# 读取超时时间socket-timeout: 0# 服务器选择超时时间server-selection-timeout: 30000# 最大等待时间max-wait-time: 120000# 最大连接空闲时间max-connection-idle-time: 0# 最大连接生存时间max-connection-life-time: 0# 日志配置
logging:level:org.springframework.data.mongodb: DEBUGorg.mongodb.driver: DEBUG
🔧 MongoDB配置类
package com.example.demo.config;import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;@Configuration
@EnableMongoRepositories(basePackages = "com.example.demo.repository")
public class MongoConfig extends AbstractMongoClientConfiguration {@Value("${spring.data.mongodb.database}")private String databaseName;@Value("${spring.data.mongodb.uri}")private String mongoUri;@Overrideprotected String getDatabaseName() {return databaseName;}@Overridepublic MongoClient mongoClient() {return MongoClients.create(mongoUri);}/*** 自定义MongoTemplate配置*/@Beanpublic MongoTemplate mongoTemplate() throws Exception {MongoTemplate mongoTemplate = new MongoTemplate(mongoClient(), getDatabaseName());// 移除_class字段MappingMongoConverter converter = (MappingMongoConverter) mongoTemplate.getConverter();converter.setTypeMapper(new DefaultMongoTypeMapper(null));return mongoTemplate;}
}
📊 文档实体类
1. 用户文档
package com.example.demo.document;import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;import jakarta.validation.constraints.*;
import java.time.LocalDateTime;
import java.util.List;@Document(collection = "users")
public class UserDocument {@Idprivate String id;@Field("username")@Indexed(unique = true)@NotBlank(message = "用户名不能为空")@Size(min = 2, max = 50, message = "用户名长度必须在2-50个字符之间")private String username;@Field("email")@Indexed(unique = true)@NotBlank(message = "邮箱不能为空")@Email(message = "邮箱格式不正确")private String email;@Field("password")@NotBlank(message = "密码不能为空")@Size(min = 6, message = "密码长度不能少于6位")private String password;@Field("age")@Min(value = 0, message = "年龄不能小于0")@Max(value = 150, message = "年龄不能大于150")private Integer age;@Field("phone")@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")private String phone;@Field("address")private Address address;@Field("hobbies")private List<String> hobbies;@Field("profile")private UserProfile profile;@Field("status")private Integer status = 1; // 0-禁用 1-启用@Field("create_time")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;@Field("update_time")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime updateTime;// 内嵌文档:地址public static class Address {private String province;private String city;private String district;private String detail;// 构造函数public Address() {}public Address(String province, String city, String district, String detail) {this.province = province;this.city = city;this.district = district;this.detail = detail;}// Getter和Setter方法public String getProvince() { return province; }public void setProvince(String province) { this.province = province; }public String getCity() { return city; }public void setCity(String city) { this.city = city; }public String getDistrict() { return district; }public void setDistrict(String district) { this.district = district; }public String getDetail() { return detail; }public void setDetail(String detail) { this.detail = detail; }}// 内嵌文档:用户档案public static class UserProfile {private String avatar;private String nickname;private String bio;private String website;// 构造函数public UserProfile() {}// Getter和Setter方法public String getAvatar() { return avatar; }public void setAvatar(String avatar) { this.avatar = avatar; }public String getNickname() { return nickname; }public void setNickname(String nickname) { this.nickname = nickname; }public String getBio() { return bio; }public void setBio(String bio) { this.bio = bio; }public String getWebsite() { return website; }public void setWebsite(String website) { this.website = website; }}// 构造函数public UserDocument() {this.createTime = LocalDateTime.now();this.updateTime = LocalDateTime.now();}public UserDocument(String username, String email, String password) {this();this.username = username;this.email = email;this.password = password;}// Getter和Setter方法public String getId() { return id; }public void setId(String id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }public String getPassword() { return password; }public void setPassword(String password) { this.password = password; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }public String getPhone() { return phone; }public void setPhone(String phone) { this.phone = phone; }public Address getAddress() { return address; }public void setAddress(Address address) { this.address = address; }public List<String> getHobbies() { return hobbies; }public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; }public UserProfile getProfile() { return profile; }public void setProfile(UserProfile profile) { this.profile = profile; }public Integer getStatus() { return status; }public void setStatus(Integer status) { this.status = status; }public LocalDateTime getCreateTime() { return createTime; }public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }public LocalDateTime getUpdateTime() { return updateTime; }public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; }@Overridepublic String toString() {return "UserDocument{" +"id='" + id + '\'' +", username='" + username + '\'' +", email='" + email + '\'' +", age=" + age +", phone='" + phone + '\'' +", status=" + status +", createTime=" + createTime +'}';}
}
2. 博客文档
package com.example.demo.document;import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.index.TextIndexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.List;@Document(collection = "blogs")
@CompoundIndex(def = "{'author': 1, 'create_time': -1}")
public class BlogDocument {@Idprivate String id;@Field("title")@TextIndexed(weight = 3)@NotBlank(message = "标题不能为空")@Size(max = 200, message = "标题长度不能超过200个字符")private String title;@Field("content")@TextIndexed(weight = 1)@NotBlank(message = "内容不能为空")private String content;@Field("summary")@Size(max = 500, message = "摘要长度不能超过500个字符")private String summary;@Field("author")@Indexedprivate String author;@Field("category")@Indexedprivate String category;@Field("tags")private List<String> tags;@Field("view_count")private Long viewCount = 0L;@Field("like_count")private Long likeCount = 0L;@Field("comment_count")private Long commentCount = 0L;@Field("published")@Indexedprivate Boolean published = false;@Field("featured")private Boolean featured = false;@Field("create_time")@Indexed@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;@Field("update_time")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime updateTime;@Field("publish_time")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime publishTime;// 引用用户文档@DBRefprivate UserDocument authorRef;// 评论列表(内嵌文档)@Field("comments")private List<Comment> comments;// 内嵌文档:评论public static class Comment {private String id;private String content;private String author;private LocalDateTime createTime;private List<Comment> replies; // 回复评论// 构造函数public Comment() {this.createTime = LocalDateTime.now();}public Comment(String content, String author) {this();this.content = content;this.author = author;}// Getter和Setter方法public String getId() { return id; }public void setId(String id) { this.id = id; }public String getContent() { return content; }public void setContent(String content) { this.content = content; }public String getAuthor() { return author; }public void setAuthor(String author) { this.author = author; }public LocalDateTime getCreateTime() { return createTime; }public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }public List<Comment> getReplies() { return replies; }public void setReplies(List<Comment> replies) { this.replies = replies; }}// 构造函数public BlogDocument() {this.createTime = LocalDateTime.now();this.updateTime = LocalDateTime.now();}public BlogDocument(String title, String content, String author, String category) {this();this.title = title;this.content = content;this.author = author;this.category = category;}// Getter和Setter方法public String getId() { return id; }public void setId(String id) { this.id = id; }public String getTitle() { return title; }public void setTitle(String title) { this.title = title; }public String getContent() { return content; }public void setContent(String content) { this.content = content; }public String getSummary() { return summary; }public void setSummary(String summary) { this.summary = summary; }public String getAuthor() { return author; }public void setAuthor(String author) { this.author = author; }public String getCategory() { return category; }public void setCategory(String category) { this.category = category; }public List<String> getTags() { return tags; }public void setTags(List<String> tags) { this.tags = tags; }public Long getViewCount() { return viewCount; }public void setViewCount(Long viewCount) { this.viewCount = viewCount; }public Long getLikeCount() { return likeCount; }public void setLikeCount(Long likeCount) { this.likeCount = likeCount; }public Long getCommentCount() { return commentCount; }public void setCommentCount(Long commentCount) { this.commentCount = commentCount; }public Boolean getPublished() { return published; }public void setPublished(Boolean published) { this.published = published; }public Boolean getFeatured() { return featured; }public void setFeatured(Boolean featured) { this.featured = featured; }public LocalDateTime getCreateTime() { return createTime; }public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }public LocalDateTime getUpdateTime() { return updateTime; }public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; }public LocalDateTime getPublishTime() { return publishTime; }public void setPublishTime(LocalDateTime publishTime) { this.publishTime = publishTime; }public UserDocument getAuthorRef() { return authorRef; }public void setAuthorRef(UserDocument authorRef) { this.authorRef = authorRef; }public List<Comment> getComments() { return comments; }public void setComments(List<Comment> comments) { this.comments = comments; }
}
🔍 Repository接口
1. 用户Repository
package com.example.demo.repository;import com.example.demo.document.UserDocument;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;@Repository
public interface UserRepository extends MongoRepository<UserDocument, String> {// 根据用户名查找用户Optional<UserDocument> findByUsername(String username);// 根据邮箱查找用户Optional<UserDocument> findByEmail(String email);// 根据用户名或邮箱查找用户Optional<UserDocument> findByUsernameOrEmail(String username, String email);// 根据年龄范围查找用户List<UserDocument> findByAgeBetween(Integer minAge, Integer maxAge);// 根据状态查找用户List<UserDocument> findByStatus(Integer status);// 根据爱好查找用户List<UserDocument> findByHobbiesContaining(String hobby);// 根据城市查找用户@Query("{'address.city': ?0}")List<UserDocument> findByCity(String city);// 根据省份查找用户@Query("{'address.province': ?0}")List<UserDocument> findByProvince(String province);// 根据创建时间范围查找用户List<UserDocument> findByCreateTimeBetween(LocalDateTime startTime, LocalDateTime endTime);// 分页查询用户Page<UserDocument> findByStatus(Integer status, Pageable pageable);// 统计用户数量long countByStatus(Integer status);// 自定义查询:根据多个条件查找用户@Query("{'$and': [{'age': {'$gte': ?0}}, {'status': ?1}, {'address.city': {'$regex': ?2, '$options': 'i'}}]}")List<UserDocument> findByComplexConditions(Integer minAge, Integer status, String cityPattern);// 查找最近注册的用户@Query(value = "{}", sort = "{'create_time': -1}")List<UserDocument> findRecentUsers(Pageable pageable);
}
2. 博客Repository
package com.example.demo.repository;import com.example.demo.document.BlogDocument;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;import java.time.LocalDateTime;
import java.util.List;@Repository
public interface BlogRepository extends MongoRepository<BlogDocument, String> {// 根据作者查找博客List<BlogDocument> findByAuthor(String author);// 根据分类查找博客List<BlogDocument> findByCategory(String category);// 根据发布状态查找博客List<BlogDocument> findByPublished(Boolean published);// 根据标题模糊查找博客List<BlogDocument> findByTitleContainingIgnoreCase(String title);// 根据标签查找博客List<BlogDocument> findByTagsContaining(String tag);// 根据作者和发布状态查找博客List<BlogDocument> findByAuthorAndPublished(String author, Boolean published);// 根据分类和发布状态分页查找博客Page<BlogDocument> findByCategoryAndPublished(String category, Boolean published, Pageable pageable);// 查找热门博客(根据浏览量)@Query(value = "{'published': true}", sort = "{'view_count': -1}")List<BlogDocument> findPopularBlogs(Pageable pageable);// 查找推荐博客List<BlogDocument> findByFeaturedAndPublished(Boolean featured, Boolean published);// 根据创建时间范围查找博客List<BlogDocument> findByCreateTimeBetween(LocalDateTime startTime, LocalDateTime endTime);// 全文搜索@Query("{'$text': {'$search': ?0}}")List<BlogDocument> findByTextSearch(String searchText);// 复合查询:根据多个条件查找博客@Query("{'$and': [{'published': true}, {'view_count': {'$gte': ?0}}, {'like_count': {'$gte': ?1}}]}")List<BlogDocument> findPopularPublishedBlogs(Long minViews, Long minLikes);// 统计博客数量long countByAuthorAndPublished(String author, Boolean published);// 聚合查询:按分类统计博客数量@Query(value = "{}", fields = "{'category': 1}")List<BlogDocument> findAllCategories();
}
🏗️ Service层实现
1. 用户服务
package com.example.demo.service;import com.example.demo.document.UserDocument;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Autowiredprivate MongoTemplate mongoTemplate;/*** 保存用户*/public UserDocument save(UserDocument user) {user.setUpdateTime(LocalDateTime.now());return userRepository.save(user);}/*** 根据ID查找用户*/public Optional<UserDocument> findById(String id) {return userRepository.findById(id);}/*** 根据用户名查找用户*/public Optional<UserDocument> findByUsername(String username) {return userRepository.findByUsername(username);}/*** 根据邮箱查找用户*/public Optional<UserDocument> findByEmail(String email) {return userRepository.findByEmail(email);}/*** 查找所有用户*/public List<UserDocument> findAll() {return userRepository.findAll();}/*** 分页查找用户*/public Page<UserDocument> findByPage(int page, int size) {Pageable pageable = PageRequest.of(page, size, Sort.by("createTime").descending());return userRepository.findByStatus(1, pageable);}/*** 根据年龄范围查找用户*/public List<UserDocument> findByAgeRange(Integer minAge, Integer maxAge) {return userRepository.findByAgeBetween(minAge, maxAge);}/*** 根据城市查找用户*/public List<UserDocument> findByCity(String city) {return userRepository.findByCity(city);}/*** 更新用户信息*/public UserDocument updateUser(String id, UserDocument userUpdate) {Optional<UserDocument> existingUser = userRepository.findById(id);if (existingUser.isPresent()) {UserDocument user = existingUser.get();user.setUsername(userUpdate.getUsername());user.setEmail(userUpdate.getEmail());user.setAge(userUpdate.getAge());user.setPhone(userUpdate.getPhone());user.setAddress(userUpdate.getAddress());user.setHobbies(userUpdate.getHobbies());user.setProfile(userUpdate.getProfile());user.setUpdateTime(LocalDateTime.now());return userRepository.save(user);}throw new RuntimeException("用户不存在: " + id);}/*** 使用MongoTemplate进行复杂更新*/public void updateUserStatus(String id, Integer status) {Query query = new Query(Criteria.where("id").is(id));Update update = new Update().set("status", status).set("updateTime", LocalDateTime.now());mongoTemplate.updateFirst(query, update, UserDocument.class);}/*** 批量更新用户状态*/public void batchUpdateUserStatus(List<String> userIds, Integer status) {Query query = new Query(Criteria.where("id").in(userIds));Update update = new Update().set("status", status).set("updateTime", LocalDateTime.now());mongoTemplate.updateMulti(query, update, UserDocument.class);}/*** 删除用户*/public void deleteUser(String id) {userRepository.deleteById(id);}/*** 统计用户数量*/public long countActiveUsers() {return userRepository.countByStatus(1);}/*** 复杂查询示例*/public List<UserDocument> complexSearch(Integer minAge, String city) {return userRepository.findByComplexConditions(minAge, 1, city);}/*** 使用MongoTemplate进行聚合查询*/public List<UserDocument> findUsersByComplexCriteria(String province, List<String> hobbies) {Query query = new Query();// 添加省份条件if (province != null && !province.isEmpty()) {query.addCriteria(Criteria.where("address.province").is(province));}// 添加爱好条件if (hobbies != null && !hobbies.isEmpty()) {query.addCriteria(Criteria.where("hobbies").in(hobbies));}// 只查询启用的用户query.addCriteria(Criteria.where("status").is(1));// 按创建时间降序排列query.with(Sort.by(Sort.Direction.DESC, "createTime"));return mongoTemplate.find(query, UserDocument.class);}
}
🎮 Controller层
package com.example.demo.controller;import com.example.demo.document.UserDocument;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import jakarta.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;@RestController
@RequestMapping("/api/mongo")
@CrossOrigin(origins = "*")
public class MongoController {@Autowiredprivate UserService userService;/*** 创建用户*/@PostMapping("/users")public ResponseEntity<UserDocument> createUser(@RequestBody @Valid UserDocument user) {UserDocument savedUser = userService.save(user);return ResponseEntity.ok(savedUser);}/*** 根据ID获取用户*/@GetMapping("/users/{id}")public ResponseEntity<UserDocument> getUserById(@PathVariable String id) {Optional<UserDocument> user = userService.findById(id);return user.map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build());}/*** 获取所有用户*/@GetMapping("/users")public ResponseEntity<List<UserDocument>> getAllUsers() {List<UserDocument> users = userService.findAll();return ResponseEntity.ok(users);}/*** 分页获取用户*/@GetMapping("/users/page")public ResponseEntity<Page<UserDocument>> getUsersByPage(@RequestParam(defaultValue = "0") int page,@RequestParam(defaultValue = "10") int size) {Page<UserDocument> users = userService.findByPage(page, size);return ResponseEntity.ok(users);}/*** 根据用户名查找用户*/@GetMapping("/users/username/{username}")public ResponseEntity<UserDocument> getUserByUsername(@PathVariable String username) {Optional<UserDocument> user = userService.findByUsername(username);return user.map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build());}/*** 根据年龄范围查找用户*/@GetMapping("/users/age")public ResponseEntity<List<UserDocument>> getUsersByAgeRange(@RequestParam Integer minAge,@RequestParam Integer maxAge) {List<UserDocument> users = userService.findByAgeRange(minAge, maxAge);return ResponseEntity.ok(users);}/*** 根据城市查找用户*/@GetMapping("/users/city/{city}")public ResponseEntity<List<UserDocument>> getUsersByCity(@PathVariable String city) {List<UserDocument> users = userService.findByCity(city);return ResponseEntity.ok(users);}/*** 更新用户*/@PutMapping("/users/{id}")public ResponseEntity<UserDocument> updateUser(@PathVariable String id,@RequestBody @Valid UserDocument user) {try {UserDocument updatedUser = userService.updateUser(id, user);return ResponseEntity.ok(updatedUser);} catch (RuntimeException e) {return ResponseEntity.notFound().build();}}/*** 更新用户状态*/@PatchMapping("/users/{id}/status")public ResponseEntity<Map<String, String>> updateUserStatus(@PathVariable String id,@RequestBody Map<String, Integer> request) {Integer status = request.get("status");userService.updateUserStatus(id, status);Map<String, String> response = new HashMap<>();response.put("status", "success");response.put("message", "用户状态更新成功");return ResponseEntity.ok(response);}/*** 删除用户*/@DeleteMapping("/users/{id}")public ResponseEntity<Map<String, String>> deleteUser(@PathVariable String id) {userService.deleteUser(id);Map<String, String> response = new HashMap<>();response.put("status", "success");response.put("message", "用户删除成功");return ResponseEntity.ok(response);}/*** 统计活跃用户数量*/@GetMapping("/users/count/active")public ResponseEntity<Map<String, Long>> countActiveUsers() {long count = userService.countActiveUsers();Map<String, Long> response = new HashMap<>();response.put("count", count);return ResponseEntity.ok(response);}/*** 复杂查询示例*/@GetMapping("/users/search")public ResponseEntity<List<UserDocument>> complexSearch(@RequestParam(required = false) Integer minAge,@RequestParam(required = false) String city) {List<UserDocument> users = userService.complexSearch(minAge, city);return ResponseEntity.ok(users);}
}
📊 最佳实践
1. 索引优化
- 为经常查询的字段创建索引
- 使用复合索引优化复杂查询
- 定期分析索引使用情况
- 避免过多索引影响写入性能
2. 文档设计
- 合理设计文档结构
- 避免过深的嵌套
- 考虑数据的读写模式
- 适当使用引用和内嵌
3. 查询优化
- 使用投影减少数据传输
- 合理使用分页
- 避免全表扫描
- 使用聚合管道优化复杂查询
本文关键词: MongoDB, NoSQL, 文档数据库, Spring Data MongoDB, 分布式存储
