springboot 操作 mongoTemplate

springboot 操作 mongoTemplate

  • maven坐标
<!-- mongodb -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
  • 实体类
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document("article")
//    @CompoundIndexes({
//            // 复合唯一索引
//            @CompoundIndex(name = "article_userId_id", def = "{'id':1,'user_id':1}", unique = true)
//    })
public class ArticleModel {
    //@Id
    ///*主键,不可重复,自带索引,可以在定义的列名上标注,需要自己生成并维护不重复的约束。
    //如果自己不设置@Id主键,mongo会自动生成一个唯一主键,并且插入时效率远高于自己设置主键。
    //在实际业务中不建议自己设置主键,应交给mongo自己生成,自己可以设置一个业务id,如int型字段,用自己设置的业务id来维护相关联的表。*/
    //@Document  //标注在实体类上,类似于entity注解,标明由mongo来维护该表,article为mongo集合名称
    //@Indexed   //声明该字段需要加索引,加索引后以该字段为条件检索将大大提高速度
    //@CompoundIndex    //复合索引,加复合索引后通过复合索引字段查询将大大提高速度。1升序-1降序
    //@Field     //代表一个字段,可以不加,不加的话默认以参数名为列名
    //@Transient //被该注解标注的,将不会被录入到数据库中。只作为普通的javaBean属性。
    //@DBRef     //关联另一个document对象
    @Id
    private Long id;
    // @Indexed
    private String name;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
}
  • mongo数据库时间格式
    mongo数据库时间格式

  • MongoRepository

import ArticleModel;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ArticleRepository extends MongoRepository<ArticleModel, Long> {
// 自定义sql
	@Query("{ 'name':{'$regex':?1}}")
    public List<ArticleModel> findArticleByName(String name);
}
  • 测试用例
import com.mongodb.client.result.UpdateResult;
import  ArticleModel;
import  ArticleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.BasicQuery;
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author qzl
 * @description:
 * @date 2022/10/28 20:49
 */
@RestController
@RequestMapping("mongoTest")
public class MongoTest {
    @Autowired
    private ArticleRepository articleRepository;
    @Autowired
    private MongoTemplate mongoTemplate;

    @GetMapping("save")
    public void save(){
        ArticleModel articleModel = new ArticleModel();
        articleModel.setId(1L);
        articleModel.setName("文章1");
        // 插入重复数据时,提示主键(_id)重复;
        //批处理操作时,可以一次性插入整个数据,效率较高
//        articleRepository.insert(articleModel);
        // 插入重复数据时,对已有数据进行更新;
        //批处理操作时,需要遍历整个数据,依次插入或更新,效率较低
        articleRepository.save(articleModel);
    }
    @GetMapping("find")
    public void find(){
        ArticleModel articleModel = new ArticleModel();
        articleModel.setId(1L);
        articleModel.setName("文章1");
        Example<ArticleModel> example = Example.of(articleModel);
        // 根据model条件查询一个
        ArticleModel articleModel1 = articleRepository.findOne(example).get();
        // 根据ID查找
        articleRepository.findById(1L);
        // 根据ids查找
        articleRepository.findAllById(Arrays.asList(1L,2L));
        // 查找全部
        List<ArticleModel> all = articleRepository.findAll(example);
        // 查询全部
        List<ArticleModel> all1 = articleRepository.findAll();
        // 根据ID倒叙排序
        Sort sort = Sort.by(Sort.Order.desc("id"));
        articleRepository.findAll();
        articleRepository.findAll(example, sort);
        //分页
        PageRequest pageOf = PageRequest.of(1, 10);
        articleRepository.findAll(pageOf);
        articleRepository.findAll(example,pageOf);
        // mongoTemplate查询
        Criteria criteria = Criteria.where("id").is(1L)// id=1
                .and("id").gte(1L)// > gt < lt >= gte <= lte
                .and("name").regex("*")// 正则查找
                .orOperator(// or查询
                        Criteria.where("id").is(2L),
                        Criteria.where("name").is("李四")
                );
         // 时间间隔查询
         /*
         //1.数据库字段类型为ISODate时,查询时条件参数为Date类型时,程序会自动更换时区。
        //2.数据库字段类型为ISODate时,查询时条件参数为时间格式字符串时,程序查询不到数据。
		if (StringUtils.isNotBlank(vo.getStartTime()) && StringUtils.isNotBlank(vo.getEndTime())) {
            criteria.andOperator(Criteria.where("createTime").gte(strToDateLong(vo.getStartTime()+" 00:00:00")),
                    Criteria.where("createTime").lt(strToDateLong(vo.getEndTime()+" 23:59:59")));
        }*/
        Query query = new Query(criteria);
        mongoTemplate.find(query,ArticleModel.class);
        // 查询分页和排序
        query.with(sort);
        query.with(pageOf);
        mongoTemplate.find(query,ArticleModel.class);
        Query querySortPage = new Query();
        querySortPage.with(sort)
                .skip(0) // 从第几条开始一共查几条
                .limit(2);   //pageSize
        List<ArticleModel> users = mongoTemplate.find(querySortPage,ArticleModel.class);
        // 查询总数
        articleRepository.count();
        articleRepository.count(example);
        long count = mongoTemplate.count(new Query(), ArticleModel.class);
        System.out.println(count);

        long count2 = mongoTemplate.count(Query.query(Criteria.where("name").is("张三")), ArticleModel.class);
        System.out.println(count2);
        // 去重
        //去重 参数1:查询条件  参数2:去重的字段  参数3:查询的集合  参数4:返回的类型
        List<String> stringList = mongoTemplate.findDistinct(new Query(), "name", ArticleModel.class, String.class);
        stringList.forEach(System.out::println);
        // 使用 json 字符串方式查询
        /*这种方式还可以支持 设定返回字段,不设置便全返回
         *_id 默认显示
         *投影中不可以同时 包容和排斥
         * "{name:0,salary:0}" √ "{name:1,salary:1}" √
         * "{name:1,salary:0}" ×
         */
        BasicQuery basicQuery = new BasicQuery("{$or:[{name:'张三'},{id:123}]}","{id:0,name:0}");
        mongoTemplate.find(basicQuery, ArticleModel.class);
    }

    @GetMapping("update")
    public void update(){
        ArticleModel articleModel = new ArticleModel();
        articleModel.setId(1L);
        articleModel.setName("文章1");
        // 同主键会更新
        articleRepository.save(articleModel);

        Update update = new Update();
        update.set("name","新文章");
        // 更新查找到的第一条
        mongoTemplate.updateFirst(Query.query(Criteria.where("name").is("文章1")),update,ArticleModel.class);
        // 多条更新
        mongoTemplate.updateMulti(Query.query(Criteria.where("name").is("文章1")),update,ArticleModel.class);
        // upsert 没有符合条件时 插入数据
        Update update1 = new Update();
        update1.setOnInsert("id",5); //当插入时,指定字段值
        update1.set("name","新文章");
        UpdateResult upsert = mongoTemplate.upsert(Query.query(Criteria.where("name").is("文章1")), update, ArticleModel.class);
        //返回值
        System.out.println(upsert.getModifiedCount());//获取本次修改的记录
        System.out.println(upsert.getMatchedCount());//获取本次匹配的记录
        System.out.println(upsert.getUpsertedId());//获取插入数据的id
    }
    @GetMapping("del")
    public void del(){
        ArticleModel articleModel = new ArticleModel();
        articleModel.setId(1L);
        articleModel.setName("文章1");
        articleRepository.delete(articleModel);
        articleRepository.deleteAll();
        articleRepository.deleteById(1L);
        //删除所有
        mongoTemplate.remove(new Query(),ArticleModel.class);
        //条件删除
        mongoTemplate.remove(Query.query(Criteria.where("name").is("王五")),ArticleModel.class);
    }

    @GetMapping("aggregation")
    public void aggregation(){
        // select
        ProjectionOperation select = Aggregation.project()
                .and("name").as("name")
                .andExclude("_id");  // 排除ID
        // where
        Criteria criteria = Criteria.where("id").is(1);
            Pattern pattern = Pattern.compile("^.*文章.*$", Pattern.CASE_INSENSITIVE);
            criteria.and("name").regex(pattern);
        MatchOperation where = Aggregation.match(criteria);
               // 排序
//        SortOperation sort = Aggregation.sort(Sort.by(Sort.Order.desc("mysqlId")));
        // 分组
        GroupOperation group = Aggregation.group("id")
                .first("id").as("id")
                .first("name").as("name")// 查询分组之后的字段,在project中有的
                .count().as("count");
        TypedAggregation<ArticleModel> liveTypedAggregation = Aggregation.newAggregation(
                ArticleModel.class,
                where,  /*sort,*/ select, group);
        // 返回对象
        mongoTemplate.aggregate(liveTypedAggregation, ArticleModel.class).getMappedResults();
        // 返回map
        mongoTemplate.aggregate(liveTypedAggregation, Map.class).getMappedResults();
        // 分页
        SkipOperation skip = Aggregation.skip(getPageInfo(1,10));//跳到第几个开始
        LimitOperation limit = Aggregation.limit(10);//查出多少个数据
        TypedAggregation<ArticleModel> liveTypedAggregation = Aggregation.newAggregation(
                ArticleModel.class,
                where, select, group,skip,limit);
        mongoTemplate.aggregate(liveTypedAggregation, Map.class).getMappedResults();
        // $facet 多面分组,不太懂自己搜一下吧
        // 总数
        FacetOperation facet = Aggregation.facet(Aggregation.count().as("total")).as("total")
                .and(skip, limit).as("list");
      TypedAggregation<ArticleModel> liveTypedAggregation = Aggregation.newAggregation(
                ArticleModel.class,
                where, select, group,facet);
        mongoTemplate.aggregate(liveTypedAggregation, Map.class).getMappedResults();
        // 返回样式
        // {"list":[{"_id":{"name":"Maven教程","mysqlId":109},"name":"文章","id":1,"count":1}],"total":[{"total":总条数}]}
    }
    // 每页条数,页数
 public Long getPageInfo(Interger pageSize, Integer pageNum) {
        long startPage = 0L;
        if (null == pageNum || pageNum < 1) {
            pageNum = 1;
        }
        if (null == pageSize || pageSize < 1) {
            pageSize = 10000;
        }
        if (pageNum > 1) {
            startPage = (long) (pageNum - 1) * pageSize;
        }
        return startPage;
    }
    /*** 添加文档主要介绍两种方式:
     mongoTemplate.insert("实体对象","集合名");   往集合插入数据的方式
     mongoTemplate.save(对象,集合名(可省略));  参数必须是对象
     insert和save都适用
     不写集合名,默认对象类名作为集合名(如实体类是A  集合名是a)
     写集合名,则把数据写到对应集合下
     1.void save(Object var1);                传入对象,不传集合名
     2.void save(Object var1, String var2);   传入对象,传集合名
     3.void insert(Object var1);              传入对象,不传集合名
     4.void insert(Object var1, String var2); 传入对象,传集合名
     5.void insert(Collection<? extends Object> var1, Class<?> var2);
     下面三个方法是批量插入的实现方法
     6.void insert(Collection<? extends Object> var1, String var2);
     7.void insertAll(Collection<? extends Object> var1);
     查询mongodb的操作:
     find 和findone方法都有两种实现
     1.List<T> find(Query var1, Class<T> var2)               不指定集合名
     2.List<T> find(Query var1, Class<T> var2, String var3)  指定集合名
     3.<T> T findOne(Query var1, Class<T> var2);             不指定集合名
     4.<T> T findOne(Query var1, Class<T> var2, String var3);指定集合名
     eg。
     maxvalue在数据库中就对应一个集合,可以不指定集合名直接查询
     Sl6512014 在数据对应很多集合  必须知道集合名才能查询出数据
     *
     findall
     1.<T> List<T> findAll(Class<T> var1);   根据类型查询所有
     2.<T> List<T> findAll(Class<T> var1, String var2);  查询集合下的该类型数据
     findById:
     <T> T findById(Object var1, Class<T> var2);  var1  是mongodb的_id子段值
     <T> T findById(Object var1, Class<T> var2, String var3);    指定集合名
     更新操作:
     updateFirst  更新符合条件的第一条   updateMulti  更新多个,符合条件都会更改
     //修改第一条符合条件数据
     1.WriteResult updateFirst(Query var1, Update var2, Class<?> var3);                 指定类型
     2.WriteResult updateFirst(Query var1, Update var2, String var3);                   更新操作指定集合名
     3.WriteResult updateFirst(Query var1, Update var2, Class<?> var3, String var4);    详细指定类型和集合名
     //批量修改
     4.WriteResult updateMulti(Query var1, Update var2, Class<?> var3);                 指定类型
     5.WriteResult updateMulti(Query var1, Update var2, String var3);                   指定集合名
     6.WriteResult updateMulti(Query var1, Update var2, Class<?> var3, String var4);    详细指定类型和集合名
     //同updateFirst
     7.WriteResult upsert(Query var1, Update var2, Class<?> var3);
     8.WriteResult upsert(Query var1, Update var2, String var3);
     9.WriteResult upsert(Query var1, Update var2, Class<?> var3, String var4);
     删除操作:
     1.WriteResult remove(Object var1);
     2.WriteResult remove(Object var1, String var2);
     3.WriteResult remove(Query var1, Class<?> var2);                根据条件删除
     4.WriteResult remove(Query var1, Class<?> var2, String var3);   详细指定类型和集合名进行删除
     5.WriteResult remove(Query var1, String var2);                 指定集合名进行删除
     其他一些操作:简单介绍:
     //查询出后删除
     <T> List<T> findAllAndRemove(Query var1, String var2);    指定集合名
     <T> List<T> findAllAndRemove(Query var1, Class<T> var2);   指定类型
     <T> List<T> findAllAndRemove(Query var1, Class<T> var2, String var3); 在集合下查询删除的类型数据
     //查处后修改
     <T> T findAndModify(Query var1, Update var2, Class<T> var3);    指定修改类型
     <T> T findAndModify(Query var1, Update var2, Class<T> var3, String var4);  在集合下修改的数据类型
     <T> T findAndModify(Query var1, Update var2, FindAndModifyOptions var3, Class<T> var4);
     <T> T findAndModify(Query var1, Update var2, FindAndModifyOptions var3, Class<T> var4, String var5);
     <T> T findAndRemove(Query var1, Class<T> var2);
     <T> T findAndRemove(Query var1, Class<T> var2, String var3);
     //判断是否存在
     boolean exists(Query var1, String var2);
     boolean exists(Query var1, Class<?> var2);
     boolean exists(Query var1, Class<?> var2, String var3);
     is相当于等于
     in相当于sql中的in
     ne相当于不等于
     orOperator接受多个条件,组成or逻辑  addOperator同理
     Criteria.where("author").is("mongodb")  author = mongodb的数据
     Criteria.where("serial").lte(500).and("st").is("1703230781").and("c").in("5.7")   多条件的查询
     Criteria.where("st").exists(true)   判断这个字段存在
     Criteria.where("serial").ne(1)    不等于1的数据
     Criteria.where("serial").nin(1)    nin 不在这个范围中
     Criteria.where("serial").is(3).orOperator().is().andOperator() 追加or条件或者and条件
     Criteria.where("a").regex("1")   模糊查询   可以用正则表达式
     query6.with(new Sort(Sort.Direction.DESC,"a"));  按照a字段把结果降序
     query6.skip(n);    跳过结果集的第n个   超过总条数就是啥都不输出   n<=0  时 查询到结束不跳过
     query6.skip(n).limit(m)   跳过n条并显示m条记录
     query6.addCriteria(Criteria.where("b").is("11"));   再加条件  查询子段不能是上一个query查询过的子段
     query6.maxScan(6).skip(-2);   先截取六条数据再跳过两条
     分页查询               query.with(new PageRequest(1, 5));


     DBObject dbObject = new BasicDBObject();
     //dbObject.put("name", "zhangsan");  //查询条件

     BasicDBObject fieldsObject=new BasicDBObject();
     //指定返回的字段
     fieldsObject.put("name", true);
     fieldsObject.put("age", true);
     fieldsObject.put("sex", true);

     Query query = new BasicQuery(dbObject,fieldsObject);
     List<Person> user = mongoTemplate.find(query, Person.class);
     注解
     @Id
     主键,不可重复,自带索引,可以在定义的列名上标注,
     需要自己生成并维护不重复的约束。如果自己不设置@Id主键,
     mongo会自动生成一个唯一主键,并且插入时效率远高于自己设置主键。
     原因可参考上一篇mongo和mysql的性能对比。

     @Document(collection = "sys_user")
     注解@JsonFormat:后端格式化日期后返回给前端
     注解 @Builder.Default:设置默认值
     注解@DBRef:设置对象的关联
     注解@JsonIgnore:后端返回给前端时忽略此字段
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     注解@Transient:此字段不会映射到数据库 被该注解标注的,将不会被录入到数据库中。只作为普通的javaBean属性。
     给映射存储到 mongodb 的字段取别名
     在 java bean 中字段名为 firstName,存储到 mongo 中 key 为 fName

     @Field("fName")
     private String firstName;

     @Indexed
     声明该字段需要加索引,加索引后以该字段为条件检索将大大提高速度。
     唯一索引的话是@Indexed(unique = true)。
     也可以对数组进行索引,如果被索引的列是数组时,MongoDB会索引这个数组中的每一个元素。
     也可以对整个Document进行索引,排序是预定义的按插入BSON数据的先后升序排列。
     也可以对关联的对象的字段进行索引,譬如User对关联的address.city进行索引。(注解怎么写还不清楚,待查)


     注解 不获取 0 Doc实体类的password 字段  1相反获取的字段 用在接口方法上面
     @Query(fields = "{ 'password' : 0}")
     List<Doc> findByType(String type, Pageable pageable);




     ****/
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值