使用mongo过程中 无知造成的坑

1,616 阅读2分钟

先贴个官方文档 docs.spring.io/spring-data…

先从实体说起

  • @Indexed索引注解必须要@Document标识的类才能生效
  • 文档嵌套注解咋写? eg:baseInfoClues 就是个嵌套文档
@Document("scrm_clues_pool")//对应数据库表名
class CluesPool {
    @Id
    var id: String = "" //@Id 主键对应数据是object类型

    /**
     * 文件docunguid 单个文件编号
     */
    @Indexed //索引
    var fileUid: String? = ""
    
    /**
     * 基础字段
     */
    var baseInfoClues: CluesPoolBaseInfo? = CluesPoolBaseInfo()
    
    /**
     * 广告字段
     */
    var ad: CluesAd? = CluesAd()
}
class CluesPoolBaseInfo : BaseInfoClues() {
    @ApiModelProperty(value = "线索ID")
    @Indexed(unique = true) //唯一键索引
    open var outCluesId: String? = "";
}
  • What??加了注解没有自动生成索引 我内心也是MMP 那是什么问题呢?

  • 在MongoDB 3.x开始,自动建立索引功能默认关闭 配置文件加上

    spring:
      data:
        mongodb:
          auto-index-creation: true
    

实体搞完了 是不是该CRUD??

  • spring-data-mongodb 提供两种方式 MongoRepository和mongoTemplate

  • 对于简单查询使用MongoRepository继承下就行了 里面提供了简单的查询

    public interface CluesPoolRepository extends MongoRepository<CluesPool, String> 
    

    那还需要其他字段查询怎么办???根据名称来的。详情字段可以看官方 docs.spring.io/spring-data…

    findByLastnameAndFirstname
    对应sql … where x.lastname = ?1 and x.firstname = ?2
    
  • 写了这么多年CRUD 不搞点复杂的? mongoTemplate就能满足你的需求 条件你随便搞

         Criteria criteria = new Criteria("fileUid").is(fileGuid).and("errorCode").is(0);
            Query query = new Query(criteria);
            List<OriginalClues> originalClues = mongoTemplate.find(query, OriginalClues.class, "scrm_original_clues");
    
  • 多表联查就是mysql 最常见的 so easy

    select scrm_clues_pool.*  from scrm_original_clues
    left join scrm_clues_pool 
    on scrm_clues_pool.id=scrm_original_clues.id
    where scrm_clues_pool.a=2 and scrm_clues_pool.key is null
    
  • mongo里面就让人很陌生 可能用的少

    db.scrm_original_clues.aggregate([
       {
         $lookup:
           {
             from: "scrm_clues_pool",
             localField: "_id",
             foreignField: "_id",
             as: "inventory_docs"
           }
      },
      { $match : {"inventory_docs" : [ ]} }
    ])
    
  • 你可能知道多表联查 look look 这玩意怎么转化成java代码 我此刻想法有一种自动转化工具就好了 注意mongo主键是 _id

     LookupOperation lookupOperation = LookupOperation.newLookup().from("scrm_clues_pool")
                        .localField("_id")   //主表关联字段
                        .foreignField("_id")   //从表关联字段
                        .as("wrong_clues");   //查询结果名
                MatchOperation matchOperation = new MatchOperation(Criteria.where("fileUid").is(fileGuid).and("errorCode").is(0).and("wrong_clues").size(0));
                Aggregation aggregation = Aggregation.newAggregation(lookupOperation, matchOperation);
                List<OriginalClues> result = mongoTemplate.aggregate(aggregation, "scrm_original_clues", OriginalClues.class).getMappedResults();
    
    • 注意点: save/insert区别

    • save 根据Id判断 存在就插入不存在更新

    • insert就是插入

mongo批量插入问题

  • mongo批量插入很简单

     originalCluesRepository.insert(list)
    
  • 设置了唯一键 唯一键异常 批量插入中间出现异常 后面数据会发生什么???

  • 异常发生 后面数据就不再插入 唯一键异常下面可以捕获

    ex.getCause() instanceof MongoBulkWriteException
    
  • 如果我想抛出异常 不影响后面数据执行 可不可以 mongo这么吊,当然可以 BulkMode.UNORDERED:表示并行处理 有异常就不会影响其他

       BulkOperations ops = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "scrm_clues_pool");
                    ops.insert(poolList);
                    // 执行操作
                    ops.execute();
    

注意点

  • mongo数据类型一致才能匹配 id是object类型
  • 那么问题既然id是object类型 如果id 作为外键怎么弄 我也不知道 求解??