常用查询

类似mysql 的like

// 原生查询
{name:/名字/}
// java 驱动查询
document.put("page_html", Pattern.compile("名字"));
// 分页
 Pageable pageable = new PageRequest(pageNum,pageSize);
//创建排序规则
Sort sort = new Sort(Sort.Direction.DESC, "cTime");
// 带入
Query query = new Query();
query.with(pageable);
query.with(sort);
// 精确查询
//如果name精确查询
if(!StringUtils.isEmpty(name)){
    query.addCriteria(
        Criteria.where("name").is(name)
    );
}
// 模糊查询
//如果name使用模糊查询则 创建正则
Pattern pattern= Pattern.compile("^.*"+name+".*$", Pattern.CASE_INSENSITIVE);
if(!StringUtils.isEmpty(name)){
    query.addCriteria(
        new Criteria().and("name").regex(pattern)
    );
}
// 时间段范围查询
if(!StringUtils.isEmpty(stime)){
     query.addCriteria(
           new Criteria().andOperator(
                Criteria.where("cTime").gte(stime),
                Criteria.where("cTime").lte(etime)
           )
     );
}
// 查询总行数
Long count = mongoTemplate.count(query,GoodsModel.class);
// 返回指定字段
Query query=new Query();
query.addfields().include("你要返回的字段1");
query.addfields().include("你要返回的字段2");
query.addfields().exclude("你不返回的字段");
query.addCriteria(Criteria.where("XM").ne(null));//你要添加的查询
return mongoTemplate.find(query,你要返回的类型.class);

关联查询

@DBRef

// 关联查询
        long startSkip = 0;
        Criteria criteria = new Criteria();
        Pattern pattern = Pattern.compile("^.*" + "免费余额" + ".*$", Pattern.CASE_INSENSITIVE);
        criteria.and("name").regex(pattern);
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.lookup("activity_info", "ak", "_id", "ActivityInfo"),
                Aggregation.match(criteria),
                Aggregation.skip(startSkip),
                Aggregation.limit(10));
        List<AccountBalanceTypeVo> list = mongoTemplate.aggregate(aggregation, "account_balance_type", AccountBalanceTypeVo.class).getMappedResults();
        System.out.println(list);

 原生查询

//假如说我们关联查询时候就要加条建
db.student22.aggregate([
     {$lookup:{
          from:"parent22", //关联从表的表名
          let: {
                    nm: "$name", // 定义要筛选的字段
                },
                pipeline: [{
                    $match: {
                        $expr: {
                            $eq: ["张1","$name"] // 筛选从表name等于张1的信息
                        }
                    },
                }
            //下面还可以继续指定其他管道阶段符合
],
          as:"pr" //给结果起个别名
     }
   }
])

 常用注解

@Id
        /*主键,不可重复,自带索引*/
        @Document
        /*标注在实体类上,类似于hibernate的entity注解,标明由mongo来维护该表
        org.springframework.data.mongodb.core.mapping.Document.class
        把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。*/
        @Document(collection=“mongodb 对应 collection 名”)

        // 若未加 @Document ,该 bean save 到 mongo 的 user collection
        // 若添加 @Document ,则 save 到 reUser collection
        @Document(collection=“reUser”)
        public class User{
        }
        
        @Indexed
        /*声明该字段需要加索引,加索引后以该字段为条件检索将大大提高速度。
        唯一索引的话是@Indexed(unique = true)。
        也可以对数组进行索引,如果被索引的列是数组时,MongoDB会索引这个数组中的每一个元素。
        也可以对整个Document进行索引,排序是预定义的按插入BSON数据的先后升序排列。*/
        @CompoundIndex
        /*复合索引,加复合索引后通过复合索引字段查询将大大提高速度。*/
        @Document
        @CompoundIndexes({
                @CompoundIndex(name = “age_idx”, def = “{‘lastName’: 1, ‘age’: -1}”)
        })
        /*写法如上,lastName和age将作为复合索引,数字参数指定索引的方向,1为正序,-1为倒序。方向对单键索引和随机存不要紧,
        但如果你要执行分组和排序操作的时候,它就非常重要了。*/
        public class Person {
        }
        @Field
        /*代表一个字段,可以不加,不加的话默认以参数名为列名。
        给映射存储到 mongodb 的字段取别名
        在 java bean 中字段名为 firstName,存储到 mongo 中 key 为 fName
         */
        @Field(“fName”)
        private String firstName;

        @Transient
        // 被该注解标注的,将不会被录入到数据库中。只作为普通的javaBean属性。

        @DBRef
        // 关联另一个document对象。类似于mysql的表关联,但并不一样,mongo不会做级联的操作。

        @JsonFormat
        // 后端格式化日期后返回给前端
        @JsonFormat(pattern = “yyyy-MM-dd”, timezone = “GMT+8”)
        private Date birthday;//生日

        @JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone = “GMT+8”)
        private Date createTime;//创建时间

        @JsonFormat(pattern = DateUtils.LONG_TIME_FORMAT, timezone = “GMT+8”)
        private Date modifyTime;//修改时间

 

 开启事务

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.MongoTransactionManager;

@Configuration
public class TransactionConfig {

    @Bean
    MongoTransactionManager transactionManager(MongoDbFactory factory){
        return new MongoTransactionManager(factory);
    }

}

使用事务

@Transactional(rollbackFor = Exception.class,value = "transactionManager")
public void saveTest(Mongo test) {
    mongoTemplate.save(test);
    int i = 1/0;
}

 

在启动类上加上事务注解@EnableTransactionManagement

开启事务常见问题

  • 1.MongoDB的版本必须是4.0
  • 2.MongoDB事务功能必须是在多副本集的情况下才能使用,否则报错"Sessions are not supported by the MongoDB cluster to which this client is connected",4.2版本会支持分片事务。
  • 3.事务控制只能用在已存在的集合中,也就是集合需要手工添加不会由jpa创建会报错"Cannot create namespace glcloud.test_user in multi-document transaction."
  • 4.多数据源时需要指定事务 @Transactional(value = "transactionManager") 如果只有1个数据源不需要指定value
  • 5.事务注解到类上时,该类的所有 public 方法将都具有该类型的事务属性,但一般都是注解到方法上便于实现更精确的事务控制
  • 6.事务传递性,事务子方法上不必添加事务注解,如果子方法也提供api调用可用注解propagation = Propagation.REQUIRED也就是继承调用它的事务,如果没有事务则新起一个事务
  • 7.启动类上的@EnableTransactionManagement注解,并不是像网上所说必需添加的注解,因为spring boot 默认开始了这个注解的。
  • 8.有人说:注解必须是@Transactional(rollbackFor = { Exception.class }) 测试并不需要rollbackFor = { Exception.class },因为本例中自定义异常类继承自RuntimeException spring boot事物默认在遇到RuntimeException不论rollbackFor的异常是啥,都会进行事务的回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚
    具体rollbackFor用法可参考:
    Spring中的@Transactional(rollbackFor = Exception.class)属性详解一次Spring Transactional嵌套事务使用不同的rollbackFor的分析



作者:DevMuYuer