springboot 整合 mongodb

springboot 整合 mongodb

环境: spring boot 2.x ; mongodb v4.2.0 单机

目录


一、pom
二、配置
1. Mongodb 数据库配置
2.事务 配置
三、mongoDB 常用类型说明
四、MongoDB 常用操作
1. 查询全部
2. 指定条件进行查询,以及And条件
3. 使用OR 来进行查询
4. 比较查询
5. IN 查询
6. Count
7. 分页
8. 模糊查询
9. 不等于
10. 排序
11. 不包含 not in
12. 编辑
五、JAVA 整合mongodb 常用操作
Ⅰ、使用 JPA 去操作
   新增
   条数查询
   查询
   删除
   分页
   ExampleMatcher说明
Ⅱ、使用 template 去操作
   多条件查询
   返回特定的字段
   区间查询
   模糊查询
   修改数据
Ⅲ、template-分页
六、Filters的一些操作


正文

一、pom

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

二、配置

1. Mongodb 数据库配置

# mongodb 数据库
spring.data.mongodb.database=test1
# mongodb 服务器地址
spring.data.mongodb.uri=mongodb://192.168.137.128
# Redis 服务器连接端口
spring.data.mongodb.port=27017

2.事务 配置(注意:单节点的mongodb无法开启事务)

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

开启事务

@SpringBootApplication
@EnableTransactionManagement
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

三、mongoDB 常用类型说明

类型描述
String字符串类型
Integer整数类型
Bollean布尔值
Double双精度浮点值
Arrays数组或列表
Timestamp时间搓
Object内嵌文档
Date日期时间
Object ID对象id
Binary Data二进制数据
Code代码类型,已知支持javaScript
Regular正则类型

四、MongoDB 常用操作

getCollection(tableName); – 获得表的Collection

1. 查询全部

db.collection.find();

e.g.:

db.getCollection('dept_info').find({}); --查询全部数据
db.getCollection('dept_info').find({},{name:1,sex:1})-- 只返回表的 name和sex 字段

2. 指定条件进行查询,以及And条件

db.collection.find(field:search,…)

e.g.:

db.getCollection('dept_info').find({"name":"王重阳"}); --查询name为王重阳的
db.getCollection('dept_info').find({"name":"王重阳","sex":"男"}); --查询name为王重阳,sex为男的

3. 使用OR 来进行查询

db.collection.find({"$or":[{field:search},…]})

e.g.:

db.getCollection('dept_info').find("$or":[{"name":"王重阳"},{"sex":"男"}]); -- 查询name为王重阳或者sex 为男的

4. 比较查询

db.collection.find({field:{"$gt":1000}});

g t ( > ) 、 gt(>)、 gt(>)gte(>=)、 l t ( < ) 、 lt(<)、 lt(<)lte(<=)

e.g.:

db.getCollection('dept_info').find({"salary":{"$gte":1000}}); -- 查询 salary >=1000 的
db.getCollection('dept_info').find({"salary":{"$gte":1000},"salary":{"$lte":65000}}); -- 查询 1000 <= salary <= 65000

5. IN 查询

db.collection.find({field:{"$in":[v1,v2,…]}});

e.g.:

db.getCollection('dept_info').find({"name":{"$in":["春香","夏香"]}}); -- 查询 name 为 春香或者 夏香的
db.getCollection('dept_info').find({"name":{"$in":["春香","夏香"]},"sex":"女"}); -- 查询 name为春香或者 夏香的 sex为女的

6. Count

db.collection.count(Bson);

e.g.:

db.getCollection('dept_info').count(); --查询 dept_info 的条数
db.getCollection('dept_info').count({"name":{"$in":["春香","夏香"]},"sex":"女"}); -- 查询 name为 name 为 春香或者 夏香的的条数

7. 分页

db.collection.find(Bson),skip(起始条数).limit(终止条数)

e.g.:

 db.getCollection('dept_info').find({"salary":{"$gte":100},"salary":{"$lte":500}}).skip(pageSize*pageNum-1).limit(pageNum); --查询salary 介于[100,500) 的 条数pageSize-(pageNum-1) 查询 pageNum;

8. 模糊查询

db.collection.find({field:/.search./});

.* search – %search 前模糊查询

search.* – search% 后模糊查询

.search. – %search% 前后模糊查询

e.g.:

db.getCollection('dept_info').find({"mobile":/136.*/}); --查询手机号 136开头的

9. 不等于

db.collection.find(field:{"$ne":search});

e.g.:

db.getCollection("dept_info").find({"name":{"$ne":"张无忌"}});--查询 name 不包括张无忌的

10. 排序

db.collection.find(Bson).sort({“field”:1});

sort({filed:1}); – 按照 field 升序

sort({filed:-1}); --按照 field 降序

e.g.:

db.getCollection("dept_info").find().sort({"salary":-1}); --按照salary 降序查询

11. 不包含 not in

db.collection.find({field:{"$nin":[v1,v2,…]}});

e.g.:

db.getCollection('dept_info').find({"name":{"$nin":["春香","夏香"]}}); -- 查询 name 不为 春香或者 夏香的

12. 编辑

db.collection.update(selectBson,UpdateBson);

selectBson: 查询条件bson 例如:{“name”:“张三”},以张三作为查询条件

UpdateBson: 数据修改方,注意如果不加 $set 则是文档替换 加上才是指定字段修改

e.g.:

db.getCollection('dept_info').update({"_id":"1572570469058571910510215403"},{"name" : "丘处机"}); //修改id 为  1572570469058571910510215403 的文档为 {"name" : "丘处机"}
---> 改前
{
   "_id" : "1572570469058571910510215403",
   "name" : "丘处机",
   "sex" : "男",
   "mobile" : "13892111116",
   "salary" : 888888,
   "createTimeLong" : "1572570469533",
   "_class" : "com.study.www.entity.Dept"
}
----> 改后
{
   "_id" : "1572570469058571910510215403",
   "name" : "丘处机"
}

db.getCollection('dept_info').update({"_id":"1572570469058571910510215403"},{
   "$set" : {"mobile" : "13892111116",
   "salary" : 6666666}
});
---> 改前
{
   "_id" : "1572570469058571910510215403",
   "name" : "丘处机",
   "sex" : "男",
   "mobile" : "13892111116",
   "salary" : 888888,
   "createTimeLong" : "1572570469533",
   "_class" : "com.study.www.entity.Dept"
}
----> 改后
{
   "_id" : "1572570469058571910510215403",
   "name" : "丘处机",
   "sex" : "男",
   "mobile" : "13892111116",
   "salary" : 6666666.0,
   "createTimeLong" : "1572570469533",
   "_class" : "com.study.www.entity.Dept"
}

五、JAVA 整合mongodb 常用操作

Ⅰ、使用 JPA 去操作

dao继承 MongoRepository<T,String>

e.g.:

@Repository
public interface DeptRepository extends MongoRepository<Dept,String> {

}

新增

repository.save(dept);

条数查询

repository.count(Example);

e.g.:

Dept dept = new Dept();
dept.setName(name);
ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.hashCode());
Example<Dept> example = Example.of(dept, matcher);
return  deptRepository.count(example);

查询

repository.deptRepository.(Example);

repository.findById(String id);

e.g.:

deptRepository.findById(id).orElseGet(() -> null); --根据id去查询

Dept dept = new Dept();
dept.setName(name);
ExampleMatcher matcher = ExampleMatcher.matching()
                .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.hashCode());
Example<Dept> example = Example.of(dept, matcher);
return  deptRepository.findById(example);

删除

repository.deleteById(String id);

分页

Page pageResult= Repository.findAll(example, pageRequest);

PageRequest pageRequest = PageRequest.of(startInt, endInt, Sort.Direction.DESC, "id");
Dept dept = new Dept();
dept.setMobile(mobile);
ExampleMatcher exampleMatcher = ExampleMatcher.matching().withMatcher("mobile", ExampleMatcher.GenericPropertyMatchers.startsWith());
Example<Dept> example = Example.of(dept, exampleMatcher);
return  deptRepository.findAll(example, pageRequest);

ExampleMatcher 说明
ExampleMatcher可以构成Example来进行查询条件的制作;如下
ExampleMatcher.GenericPropertyMatchers.hashCode() -- 等同于 sql 中的 == ,mongo中的{field,v}
ExampleMatcher.GenericPropertyMatchers.startWith() -- 等同于 sql中的 search%, mongo中的{field,/v.*/}
ExampleMatcher.GenericPropertyMatchers.endWith() -- 等同于 sql中的 %search, mongo中的{field,/.*v/}​

Ⅱ、使用 template 去操作

多条件查询
//根据 mobile id createTimeLong 去查询 等同于SQL where mobile = X OR id = X OR createTimeLong = X
//转为mongo:  db.collection.find({"$or":[{"mobile":X},{"id":X},{"createTimeLong":X}]})
Criteria criteriaMobile = Criteria.where("mobile").is(search);
Criteria criteriaSearch = Criteria.where("id").is(search);
Criteria criteriaTimeLong = Criteria.where("createTimeLong").is(search);
Criteria criteria = new Criteria().orOperator(criteriaSearch, criteriaMobile,criteriaTimeLong);
Query query = new Query().addCriteria(criteria);
// 转为 BSON 等同于
Bson mobileQueryBson = Filters.eq("mobile", search);
Bson idQueryBson = Filters.eq("id", search);
Bson createTimeLongQueryBson = Filters.eq("createTimeLong", search);
Bson queryBson = Filters.or(mobileQueryBson, idQueryBson, createTimeLongQueryBson);
MongoCollection<Document> collection = mongoTemplate.getCollection(
    Objects.requireNonNull(TableUtils.getTableName(Dept.class)));
FindIterable<Document> documents = collection.find(queryBson);
return  mongoTemplate.findOne(query, Dept.class);

返回特定的字段
// 根据 name 做全模糊查询,回显 name,_id,sex 等同于SQL: select _id,name,sex from table where name like '%search%'
//转为mongodb: db.collection.find({"name":/.*search.*/})
Bson queryName = Filters.regex("name", ".*" + name + ".*");
//回显的字段
Document document = new Document();
document.put("name",1);
document.put("_id",1);
document.put("sex",1);
return pageHelper.pageQuery(queryName, Dept.class, pageNum, pageSize,selectDocument);

区间查询
// 根据 salary 做区间查询等同于 [starSalary,endSalary] 等同于 SQL: select * from table where salary >= 'startSalary' AND salary <= 'endSalary'
//转为 mongodb: db.collection.find({"salary":{"$gte":startSalary},"salary":{"$lte":endSalary}})
MongoCollection<Document> collection = mongoTemplate.getCollection(
	Objects.requireNonNull(TableUtils.getTableName(Dept.class))
);
//  >= startSalary
Bson startSalaryBson = Filters.gte("salary", startSalary.doubleValue()*1000);
// <= endSalary
Bson endSalaryBson = Filters.lte("salary", endSalary.doubleValue()*1000);
Bson queryBson = Filters.and(startSalaryBson, endSalaryBson);
FindIterable<Document> documents = collection.find(queryBson);
return BeanUtils.copyList(documents,Dept.class);

模糊查询
//根据 名称 OR 电话 OR 性别 做模糊查询,三者的区别 名称前后模糊,电话后模糊,性别全匹配 等同于SQL: SELECT * FROM table where name like "%search%" OR mobile like "search%" OR sex = "search"
//转为 mongodb bson: db.collection.find({"$or":[{"name":/.*136.*/},{"mobile": /136.*/},{"sex":"136"}]})
Bson queryBson = new BsonDocument();
// 前后模糊 等同于 like %search%
Bson  likeName = Filters.regex("name", ".*" + search + ".*");
//  后模糊 等同于 like search%
Bson likeMobile = Filters.regex("mobile",  search + ".*");
// 等同于  ==
Bson eqSex = Filters.eq("sex", search);
// 使用 or 将三者拼接
queryBson = Filters.or(likeMobile, likeName, eqSex);
return  pageHelper.pageQuery(queryBson, Dept.class, pageNum, pageSize);

删除数据
//根据名称去删除数据,等同于SQL: delete from table where name = "search"
//转为 mongod bson: db.getCollection('dept_info').remove({name:"name"})
Bson queryBson = Filters.eq("name", name);
MongoCollection<Document> collection = mongoTemplate.getCollection(Objects.requireNonNull(TableUtils.getTableName(Dept.class)));
collection.deleteMany(queryBson);

修改数据
//根据id去修改其他信息 注意需要加上 $set 
//等同于SQL: update table set ... where id = $search$
//转为mongo bson: db.getCollection('dept_info').update({"_id":"157257046"},{"$set" : {....}})
MongoCollection<Document> collection = mongoTemplate.getCollection(Objects.requireNonNull(TableUtils.getTableName(Dept.class)));
Bson mongoIdSearch = Filters.eq("_id", dept.getId());
dept.setId(null);
HashMap<String, Object> changeMap = new HashMap<>(1);
changeMap.put("$set",dept);
BsonDocument update = BsonDocument.parse(JSONObject.toJSONString(changeMap));
collection.updateMany(mongoIdSearch,update);

Ⅲ、template-分页

mongodb中使用bson分页是:db.collection.find(Bson).skip(起始条数).limit(终止条数),

其的做法是查询出终止条数然后再减去起始条数,例如: db.collection.find().skip(50000).limit(50010)。mongodb会先查出 50010 条然后再丢弃前 50000条。我们可以利用id进行 lastId < 来操作(需要根据id进行排序)

db.collection.find({"_id":{"$gte":1000}}),skip(起始条数).limit(终止条数);

待你用心观察你会发现查询条件都在find 里面,我们大可将其抽取成为一个分页工具类如下:

@Component
public class MongoPageHelper {

    // 最小页码
    public static final int FIRST_PAGE_NUM = 1;
    /** mongodb自带得id */
    public static final String MONGO_ID = "_id";

    @Autowired
    private  MongoTemplate mongoTemplate;
    @Autowired
    private MongoConverter mongoConverter;

    @Autowired
    public MongoPageHelper(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }


    /**
     * 分页查询,不考虑条件分页,直接使用skip-limit来分页.
     *
     */
    public <T> PageResult<T> pageQuery(Bson queryBson, Class<T> clazz,Integer pageNum, Integer pageSize) {
        return pageQuery(queryBson, clazz,pageNum, pageSize, null,null);
    }


    public <T> PageResult<T> pageQuery(Bson queryBson, Class<T> clazz,Integer pageNum, Integer pageSize,String lastId) {
        return pageQuery(queryBson, clazz,pageNum, pageSize, lastId,null);
    }

    public <T> PageResult<T> pageQuery(Bson queryBson, Class<T> clazz,Integer pageNum, Integer pageSize,Document selectDocument) {
        return pageQuery(queryBson, clazz,pageNum, pageSize, null,selectDocument);
    }

    /**
     * 分页查询.
     *
     * @param queryBson Bson,构造你自己的查询条件.
     * @param clazz Mongo collection定义的 class,用来确定查询哪个集合.
     * @param pageSize 分页的大小.
     * @param pageNum 当前页.
     * @param lastId 条件分页参数, 区别于skip-limit,采用find(_id>lastId).limit分页.
     * 如果不跳页,像朋友圈,微博这样下拉刷新的分页需求,需要传递上一页的最后一条记录的ObjectId。 如果是null,则返回pageNum那一页.
     * @param <T> collection定义的class类型.
     * @param  selectDocument 查询返回的字段组.
     * @return PageResult,一个封装page信息的对象.
     */
    public <T> PageResult<T> pageQuery(Bson queryBson, Class<T> clazz,Integer pageNum, Integer pageSize,String lastId,Document selectDocument) {
        //分页逻辑
        MongoCollection<Document> collection = mongoTemplate.getCollection(Objects.requireNonNull(TableUtils.getTableName(clazz)));
        long total = collection.countDocuments(queryBson);
        final PageResult<T> pageResult = new PageResult<>();
        pageResult.setTotal(total);
        pageResult.setPageSize(pageSize);
        pageResult.setPageNum(pageNum);
        //总页数
        final Integer pages = (int) Math.ceil(total / (double) pageSize);
        if (pageNum <= 0) {
            pageNum = FIRST_PAGE_NUM;
        }
        // 如果查询页数大于总页数则为空
        if (pageNum > pages){
            pageResult.setList(Lists.newArrayList());
            return pageResult;
        }
        FindIterable<Document> findIterable = null;
        //默认根据id 排序
        Bson mongoIdAscBson = Sorts.orderBy(Sorts.ascending(MONGO_ID));
        if (StringUtils.isNotBlank(lastId)) {
            if (pageNum != FIRST_PAGE_NUM) {
                Bson lastIdBson = Filters.gt(MONGO_ID, new ObjectId(lastId));
                queryBson =Filters.and(queryBson, lastIdBson);
            }
            findIterable = collection.find(queryBson).sort(mongoIdAscBson);
        } else {
            int skip = pageSize * (pageNum - 1);
            findIterable = collection.find(queryBson).sort(mongoIdAscBson).skip(skip);
        }
        findIterable = findIterable.limit(pageSize);
        if (!ObjectUtils.isEmpty(selectDocument)) {
            findIterable.projection(selectDocument);
        }
        MongoCursor<Document> iterator = findIterable.iterator();
        List<T> list = Lists.newArrayList();
        while (iterator.hasNext() ){
            Document next = iterator.next();
            if (!ObjectUtils.isEmpty(next.get(MONGO_ID))) {
                next.put("id",next.get(MONGO_ID).toString());
            }
            list.add(mongoConverter.read(clazz,next));
        }
        pageResult.setList(list);
        return pageResult;
    }
}

六、Filters的一些操作

方法含义
Bson bson = Filters.regex(field, “." + search + ".”);field 字段名, search 搜索条件前后拼 .* 代表%的意思
Bson bson = Filters.eq(field, search);field 字段名,search 搜索条件等于SQL : where field = search
Bson bson = Filters.or(Bson…)Bson 上文的搜索条件,多个条件 OR 串联
Bson bson = Filters.gte(field, search);
同类的 gt,lt,lte
field 字段名,search 搜索条件等于SQL : where field <= search
Bson bson = Filters.or(Bson…);Bson 上文的搜索条件,多个条件 AND 串联
Bson bson = Sorts.orderBy(Sorts.ascending(field));
Sorts.orderBy(Sorts.descending(field));
field 字段名, 排序 ASC
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值