1、docker 安装
docker run -d -p 27017:27017 --name mongo mongo:latest
2、自定义数据库并创建用户
进入操作界面
docker exec -it mongo mongo xiufengd
查看现有角色
show roles;
创建相应角色用户
db.createUser({user:'admin',pwd:'admin',roles:[{role:"dbAdmin",db:"xiufengd"}]});
也可以用其他库例如admin的角色来创建用户
db.createUser({user:'admin',pwd:'admin',roles:[{role:"userAdminAnyDatabase",db:"admin"}]});
3、springboot集成测试
3.1 引包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> <version>2.7.1</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.4</version> </dependency>
3.2 yml文件
spring: data: mongodb:
#uri: mongodb://xiufengd:xiufengd@152.136.15.119:27017/test
host: 152.136.15.119
port: 27017
database: test
authentication-database: xiufengd
username: xiufengd
password: xiufengd
3.3 新建实体类
package com.example.mongodbtest.dao; import cn.hutool.core.date.DateTime; 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; import java.util.Date; /** * @author xiufengd * @date 2022/7/5 17:07 * 未来可期 */ @Data @Builder @NoArgsConstructor @AllArgsConstructor // 用Document 表明库中存储的集合名 若缺失则集合名=类名 @Document("test_bean") public class TestBean { /** * 文章id */ @Id private Long id; /** * 用户ID */ private Long userId; /** * 文章标题 */ private String title; /** * 文章内容 */ private String content; /** * 创建时间 */ private Date createTime; /** * 更新时间 */ private Date updateTime; /** * 点赞数量 */ private Long thumbUp; /** * 访客数量 */ private Long visits; public TestBean(long id, long userId, String title, String content, DateTime createTime, DateTime updateTime, long thumbUp, long visits) { this.id=id; this.userId = userId; this.title=title; this.content=content; this.createTime = createTime; this.updateTime = updateTime; this.thumbUp = thumbUp; this.visits = visits; } }
3.4 持久层
package com.example.mongodbtest.service; import com.example.mongodbtest.dao.TestBean; import org.springframework.data.mongodb.repository.MongoRepository; /** * @author xiufengd * @date 2022/7/5 17:50 * 未来可期 */ public interface ArticleRepository extends MongoRepository<TestBean, Long> { }
3.5 测试类
package com.example.mongodbtest; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Snowflake; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.json.JSONUtil; import com.example.mongodbtest.dao.TestBean; import com.example.mongodbtest.service.ArticleRepository; import lombok.extern.slf4j.Slf4j; import org.assertj.core.util.Lists; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.*; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.test.context.junit4.SpringRunner; import java.text.ParseException; import java.util.List; import java.util.stream.Collectors; /** * @author xiufengd * @date 2022/7/5 18:09 * 未来可期 */ @Slf4j @RunWith(SpringRunner.class) @SpringBootTest public class ArticleRepositoryTest { @Autowired private ArticleRepository articleRepo; @Autowired private MongoTemplate mongoTemplate; private static Snowflake snowflake = IdUtil.createSnowflake(2, 1); /** * 测试新增 */ @Test public void testSave() { TestBean article = new TestBean(1L,2L, RandomUtil.randomString(20), RandomUtil.randomString(150), DateUtil.date(), DateUtil.date(), 0L, 0L); articleRepo.save(article); // 根据ID属性进行新增或更新 mongoTemplate.save(article); log.info("【article】= {}", JSONUtil.toJsonStr(article)); } /** * 测试批量新增列表 */ @Test public void testSaveList() { List<TestBean> articles = Lists.newArrayList(); for (int i = 0; i < 10; i++) { articles.add(new TestBean(i+1,snowflake.nextId(), RandomUtil.randomString(20), RandomUtil.randomString(150), DateUtil.date(), DateUtil.date(), 0L, 0L)); } articleRepo.saveAll(articles); log.info("【articles】= {}", JSONUtil.toJsonStr(articles.stream().map(TestBean->TestBean.getId()).collect(Collectors.toList()))); } /** * 测试更新 */ @Test public void testUpdate() { articleRepo.findById(1L).ifPresent(article -> { article.setTitle(article.getTitle() + "更新之后的标题"); article.setUpdateTime(DateUtil.date()); articleRepo.save(article); log.info("【article】= {}", JSONUtil.toJsonStr(article)); }); } /** * 测试删除 */ @Test public void testDelete() { // 根据主键删除 articleRepo.deleteById(1L); // 全部删除 articleRepo.deleteAll(); } /** * 测试分页排序查询 */ @Test public void testQuery() throws ParseException { Pageable pageable = Pageable.ofSize(2).withPage(0); Sort sort = Sort.by("thumbUp", "updateTime").descending().and(Sort.by("title").ascending()); PageRequest pageRequest = PageRequest.of(0, 5, sort); Page<TestBean> page = articleRepo.findAll(pageable); List<String> collect = page.getContent().stream().map(e -> JSONUtil.toJsonStr(e)).collect(Collectors.toList()); collect.forEach(e-> System.out.println("------------------"+e)); } @Test public void update(){ articleRepo.findById(1L).ifPresent(e->{ e.setTitle("test11111"); articleRepo.save(e); }); }
@Test
public void otherUpdate(){
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(1L));
Update update = new Update();
update.inc("thumbUp",1L);
mongoTemplate.updateFirst(query,update,"test_bean");
}
@Test
public void query(){
TestBean testBean = TestBean.builder()
.title("kfbumyywyfjjx484nj8i")
.content("auich2ajagflg")
.build();
ExampleMatcher withMatcher = ExampleMatcher.matching()
// 忽略大小写
.withIgnoreCase()
// 指定"title"为精确匹配
.withMatcher("title", ExampleMatcher.GenericPropertyMatcher::exact)
// 指定"content"为模糊匹配
.withMatcher("content", ExampleMatcher.GenericPropertyMatcher::contains);
Example<TestBean> example = Example.of(testBean,withMatcher);
/**
* 排序规则
*/
Sort sort = Sort.by("updateTime").descending();
/**
* 分页
*/
PageRequest pageRequest = PageRequest.of(0, 5, sort);
/**
* 分页查询
*/
Page<TestBean> articleRepoAll = articleRepo.findAll(example, pageRequest);
/**
* 打印
*/
log.info("-------------------------"+JSONUtil.toJsonStr(articleRepoAll.getContent()));
}
@Test
public void templateQuery(){
Criteria criteria = Criteria
/**
* 精确匹配
* 等同于 where title = "e0pekgbb6r7ugtz81pxb"
*/
.where("title").is("e0pekgbb6r7ugtz81pxb")
/**
* 模糊匹配, 用正则: .*[xxx].*
* 等同于 and content like "%l1moc1%"
*/
.and("content").regex(".*l1moc1.*")
/**
* 匹配明细里的字段
* 当字段值为数组时(必须是数组,不能是数组字符串),匹配数组元素的值
* e.g. content值为 {"name":"11", "age":27}, {"name":"12", "age":23}, {"name":"13", "age":21}]的数组时
* 等同于 and content.name="111" 注意 content的类型必须是数组 list
*/
.and("content").elemMatch(Criteria.where("name").is("111"))
/**
* 匹配多个并行
* 等同于 and ( ((visits = null) or (visits = 1))and ((thumbUp = null) or (thumbUp = 1)))
* andOperator 或者 orOperator 只得都是内部条件之间的关系,最外层都是and关系
*/
.andOperator(
new Criteria().orOperator(
Criteria.where("visits").exists(false),
Criteria.where("visits").is(1)
),
new Criteria().orOperator(
Criteria.where("thumbUp").exists(false),
Criteria.where("thumbUp").is(1)
)
);
/**
* 排序规则
* Sort 遵循从左到右的排序顺序
* e.g. .sort({"updateTime":-1},{"thumbUp":-1});
* 等同于 order by updateTime desc , thumbUp desc
*/
Sort sort = Sort.by("updateTime","thumbUp").descending();
/**
* 分页 page从0开始 每页5个
* 等同于 limit 0,5
*/
PageRequest pageRequest = PageRequest.of(0, 5, sort);
Query query = Query.query(criteria).with(sort).with(pageRequest);
List<TestBean> articles = mongoTemplate.find(query, TestBean.class);
PageImpl<TestBean> page = (PageImpl<TestBean>) PageableExecutionUtils.getPage(articles,
pageRequest,()-> mongoTemplate.count(Query.query(criteria),TestBean.class));
// 打印
Optional.of(page.getContent()).ifPresent(testBean -> {
articles.forEach(testBean1 -> {
log.info("打印数据:{}",JSONUtil.toJsonStr(testBean1));
});
});
}
}
4、遇到问题
4.1 字段内容过长,超过16M,此时要用文件形式单独存储,用gridFsTemplate
public boolean updateMongo(MongoBean mongoBean) { Boolean isSuccess = Boolean.FALSE; Query query = Query.query(Criteria.where("id").is(mongoBean.getId()).and("code").is(mongoBean.getCode())); Update update = Update.update("utime", mongoBean.getUtime()); if (StringUtils.isNotBlank(mongoBean.getJson())) { gridFsTemplate.delete(Query.query(Criteria.where("filename").is(mongoBean.getId() + "_" + mongoBean.getCode()))); ObjectId objectId = gridFsTemplate.store(new ByteArrayInputStream(mongoBean.getJson().getBytes(StandardCharsets.UTF_8)), mongoBean.getId() + "_" + mongoBean.getCode()); //自定义文件名 update.set("json", objectId.toString()); } UpdateResult updateResult = mongoTemplate.updateMulti(query, update, MongoBean.class); if (updateResult.getModifiedCount() > 0) { isSuccess = Boolean.TRUE; } return isSuccess; }
4.2 查询文件存储的信息
public String queryMongoWithResult(String id, String code) { if (id == null || code == null) { return null; } try { Criteria criteria = Criteria.where("filename").is(id + "_" + code); //自定义的文件名 Query query = Query.query(criteria); GridFSFile gridfsFile = gridFsTemplate.findOne(query); GridFsResource resource = gridFsTemplate.getResource(gridfsFile); String result = new BufferedReader(new InputStreamReader(resource.getInputStream())).lines().collect(Collectors.joining()); return result; } catch (Exception e) { log.info("获取数异常"+e); } return null; }