SpringBoot 3.x 整合 MongoDB 详解
🎯 MongoDB简介
MongoDB是一个基于分布式文件存储的NoSQL数据库,由C++语言编写。它是一个面向文档的数据库,具有高性能、高可用性和易扩展性的特点。
核心特性
- 文档存储: 使用BSON格式存储数据
- 动态模式: 无需预定义表结构
- 高性能: 支持索引和内存映射
- 高可用: 支持副本集和分片
- 水平扩展: 支持自动分片
- 丰富查询: 支持复杂查询和聚合操作
核心概念
- Database: 数据库,类似于关系型数据库的数据库
- Collection: 集合,类似于关系型数据库的表
- Document: 文档,类似于关系型数据库的行
- Field: 字段,类似于关系型数据库的列
- Index: 索引,提高查询性能
- Replica Set: 副本集,提供高可用性
- Sharding: 分片,提供水平扩展
🚀 快速开始
1. 添加依赖
xml
<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配置
yaml
spring:
# MongoDB配置
data:
mongodb:
# MongoDB连接URI
uri: 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: DEBUG
org.mongodb.driver: DEBUG
🔧 MongoDB配置类
java
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;
@Override
protected String getDatabaseName() {
return databaseName;
}
@Override
public MongoClient mongoClient() {
return MongoClients.create(mongoUri);
}
/**
* 自定义MongoTemplate配置
*/
@Bean
public MongoTemplate mongoTemplate() throws Exception {
MongoTemplate mongoTemplate = new MongoTemplate(mongoClient(), getDatabaseName());
// 移除_class字段
MappingMongoConverter converter = (MappingMongoConverter) mongoTemplate.getConverter();
converter.setTypeMapper(new DefaultMongoTypeMapper(null));
return mongoTemplate;
}
}
📊 文档实体类
1. 用户文档
java
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 {
@Id
private 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; }
@Override
public String toString() {
return "UserDocument{" +
"id='" + id + '\'' +
", username='" + username + '\'' +
", email='" + email + '\'' +
", age=" + age +
", phone='" + phone + '\'' +
", status=" + status +
", createTime=" + createTime +
'}';
}
}
2. 博客文档
java
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 {
@Id
private 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")
@Indexed
private String author;
@Field("category")
@Indexed
private 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")
@Indexed
private 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;
// 引用用户文档
@DBRef
private 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
java
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
java
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. 用户服务
java
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 {
@Autowired
private UserRepository userRepository;
@Autowired
private 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层
java
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 {
@Autowired
private 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, 分布式存储