MongoDB 常见功能详解及 Spring Cloud 集成代码展示

MongoDB 常见功能详解及 Spring Cloud 集成代码展示


一、MongoDB 核心功能详解

1. 文档数据模型
  • BSON 格式:二进制 JSON,支持更多数据类型(Date、Binary 等)
  • 动态模式:同一集合中文档结构可不同
  • 嵌套文档:支持多层嵌套结构
{
  _id: ObjectId("507f191e810c19729de860ea"),
  name: "张三",
  address: {
    city: "北京",
    street: "朝阳区"
  },
  hobbies: ["阅读", "游泳"]
}
2. 索引机制
索引类型描述创建示例
单字段索引加速单个字段查询db.users.createIndex({age: 1})
复合索引多字段联合查询优化db.users.createIndex({name: 1, age: -1})
多键索引数组字段索引db.users.createIndex({hobbies: 1})
文本索引全文搜索支持db.articles.createIndex({content: "text"})
地理空间索引地理位置查询db.places.createIndex({loc: "2dsphere"})
TTL索引自动过期删除数据db.logs.createIndex({createdAt: 1}, {expireAfterSeconds: 3600})
3. 聚合框架
// 统计不同年龄段用户数量
db.users.aggregate([
  { $match: { status: "active" } },
  { $bucket: {
      groupBy: "$age",
      boundaries: [20, 30, 40, 50],
      output: {
        count: { $sum: 1 },
        names: { $push: "$name" }
      }
  }}
])
4. 事务支持
// MongoDB 4.0+ 多文档事务
session = db.getMongo().startSession();
session.startTransaction();
try {
  db.accounts.updateOne(
    { _id: "A001", balance: { $gte: 100 } },
    { $inc: { balance: -100 } }
  );
  db.accounts.updateOne(
    { _id: "B002" },
    { $inc: { balance: 100 } }
  );
  session.commitTransaction();
} catch (error) {
  session.abortTransaction();
  throw error;
}
5. 变更流(Change Streams)
// 监听集合变更
const changeStream = db.orders.watch();
changeStream.on("change", (change) => {
  print("Change detected: ", change);
});
6. 分片集群
  • 组件:Mongos(路由)、Config Server(元数据)、Shard(数据分片)
  • 分片键选择:高基数、低频率、不可变
  • 分片策略:范围分片、哈希分片

二、Spring Cloud 集成 MongoDB

1. 依赖配置
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
2. 配置连接

application.yml:

spring:
  data:
    mongodb:
      uri: mongodb://user:password@host1:27017,host2:27017/database?replicaSet=rs0&authSource=admin
      # 或者分开配置
      # host: localhost
      # port: 27017
      # database: test
      # username: user
      # password: pass
      # authentication-database: admin
3. 实体类映射
@Document(collection = "users")
public class User {
    @Id
    private String id;
    
    @Indexed(unique = true)
    private String username;
    
    private String email;
    private int age;
    
    @Field("join_date")
    private Date joinDate;
    
    @DBRef
    private List<Role> roles;
    
    // Getters and setters
}
4. Repository 接口
public interface UserRepository extends MongoRepository<User, String> {
    
    // 方法名自动查询
    List<User> findByAgeBetween(int minAge, int maxAge);
    
    // 分页查询
    Page<User> findByEmailContaining(String domain, Pageable pageable);
    
    // 自定义查询
    @Query("{'joinDate': {$gte: ?0, $lte: ?1}}")
    List<User> findUsersByJoinDateRange(Date start, Date end);
}
5. MongoTemplate 操作
@Autowired
private MongoTemplate mongoTemplate;

// 复杂查询
public List<User> findActiveUsers(String city) {
    Criteria criteria = new Criteria().andOperator(
        Criteria.where("age").gt(18),
        Criteria.where("address.city").is(city),
        Criteria.where("status").is("ACTIVE")
    );
    
    Query query = new Query(criteria)
        .with(Sort.by("joinDate").descending())
        .limit(100);
    
    return mongoTemplate.find(query, User.class);
}

// 更新操作
public void updateEmail(String userId, String newEmail) {
    Query query = new Query(Criteria.where("id").is(userId));
    Update update = new Update().set("email", newEmail);
    mongoTemplate.updateFirst(query, update, User.class);
}
6. 聚合操作
// 统计不同城市的用户数
public Map<String, Long> countUsersByCity() {
    TypedAggregation<User> aggregation = Aggregation.newAggregation(
        User.class,
        Aggregation.group("address.city").count().as("count"),
        Aggregation.project("count").and("_id").as("city")
    );
    
    AggregationResults<CityCount> results = 
        mongoTemplate.aggregate(aggregation, CityCount.class);
    
    return results.getMappedResults().stream()
        .collect(Collectors.toMap(CityCount::getCity, CityCount::getCount));
}

// 结果接收类
@Getter @Setter
public static class CityCount {
    private String city;
    private long count;
}
7. 事务管理
@Autowired
private MongoTransactionManager transactionManager;

@Transactional
public void transferPoints(String from, String to, int points) {
    // 减少发送方积分
    Query query1 = new Query(Criteria.where("username").is(from));
    Update update1 = new Update().inc("points", -points);
    mongoTemplate.updateFirst(query1, update1, User.class);
    
    // 增加接收方积分
    Query query2 = new Query(Criteria.where("username").is(to));
    Update update2 = new Update().inc("points", points);
    mongoTemplate.updateFirst(query2, update2, User.class);
}
8. 变更流监听
@Bean
public ChangeStreams changeStreams(MongoTemplate mongoTemplate) {
    return new ChangeStreams(mongoTemplate);
}

@Component
public class ChangeStreams {
    private final MongoTemplate mongoTemplate;
    
    @Autowired
    public ChangeStreams(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
        listenToUserChanges();
    }
    
    private void listenToUserChanges() {
        ChangeStreamOptions options = ChangeStreamOptions.builder()
            .filter(Aggregation.newAggregation(match(where("operationType").in("insert", "update")))
            .build();
        
        mongoTemplate.changeStream("users", options, User.class)
            .forEach(event -> {
                System.out.println("Change detected: " + event.getBody());
                // 处理变更事件
            });
    }
}

三、性能优化策略

  1. 索引优化

    • 使用 explain() 分析查询性能
    • 创建复合索引覆盖常用查询
    @Document
    @CompoundIndexes({
      @CompoundIndex(name = "name_age_idx", def = "{'name': 1, 'age': -1}")
    })
    public class User { ... }
    
  2. 读写分离

    @ReadPreference(ReadPreferenceMode.SECONDARY)
    public interface UserRepository extends MongoRepository<User, String> { ... }
    
  3. 批量操作

    // 批量插入
    List<User> users = ...;
    mongoTemplate.insert(users, User.class);
    
    // 批量更新
    BulkOperations bulkOps = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, User.class);
    users.forEach(user -> {
        Query query = new Query(Criteria.where("id").is(user.getId()));
        Update update = new Update().set("status", user.getStatus());
        bulkOps.updateOne(query, update);
    });
    bulkOps.execute();
    
  4. 连接池配置

    spring:
      data:
        mongodb:
          uri: mongodb://host/db?maxPoolSize=50&minPoolSize=5&maxIdleTimeMS=30000
    

四、安全与运维实践

  1. 安全配置

    spring:
      data:
        mongodb:
          uri: mongodb://user:password@host/db?authSource=admin&ssl=true
    
  2. 数据加密

    • 启用 TLS/SSL 传输加密
    • 使用 MongoDB 企业版字段级加密
  3. 备份策略

    # 使用 mongodump 备份
    mongodump --uri="mongodb://user:pass@host/db" --out=/backup
    
    # 使用 Ops Manager 或 Cloud Manager 管理备份
    
  4. 监控指标

    // Spring Boot Actuator 集成
    management:
      endpoints:
        web:
          exposure:
            include: health,metrics,mongodb
      metrics:
        tags:
          application: ${spring.application.name}
    

五、常见问题解决方案

  1. 连接超时

    spring:
      data:
        mongodb:
          uri: mongodb://host/db?connectTimeoutMS=3000&socketTimeoutMS=5000
    
  2. 事务重试

    @Retryable(value = MongoTransactionException.class, maxAttempts = 3)
    @Transactional
    public void performTransaction() { ... }
    
  3. 分片键选择

    • 原则:高基数、低频率、不可变
    • 避免热点:使用哈希分片键
    @Sharded
    public class Order {
        @ShardKey(shardKeyType = ShardKeyType.HASHED)
        private String orderId;
    }
    
  4. 内存优化

    // 使用 $project 减少返回数据
    db.orders.aggregate([
      { $match: { status: "completed" } },
      { $project: { _id: 1, total: 1 } }
    ])
    

生产建议

  1. 使用副本集确保高可用
  2. 启用访问控制(RBAC)
  3. 定期执行 compact 回收磁盘空间
  4. 使用 Profiler 分析慢查询
  5. 设置合理的 WiredTiger 缓存大小(建议50-80%内存)

以上内容涵盖了 MongoDB 的核心功能和 Spring Cloud 集成方案,包括文档模型、索引策略、聚合操作、事务管理以及性能优化等关键实践。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值