个人学习整理,欢迎批评指正,共同进步
依赖导入
主要依赖(必须)
<!-- springboot-mongodb 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
辅助依赖(非必须)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- mongodb 条件构建器-->
<!-- 可以避免硬编码存在的魔法值问题-->
<dependency>
<groupId>com.gitee.xiezengcheng</groupId>
<artifactId>fluent-mongo</artifactId>
<version>1.1.1</version>
</dependency>
配置文件编写
spring:
data:
mongodb:
database: webflux
host: 8.140.37.4
port: 27017
username: root
password: '123456'
authentication-database: admin
集成 springboot
repository 接口集成
1-继承 MongoRepository<实体类,主键泛型> 接口
2-使用方法名联想或使用 @Query 注解实现自定义方法
3-编写方法
@Query(value = "{'id': ?0}")
TestEntity getTestEntityById(Long id);
@Query(value = "{'username': /?0/ }")
List<TestEntity> getAllTestTntityByNameLike(String name);
@Query(value = "{'$or':[{'age':{'$lt': ?0 }},{'age':{'$gt': ?1 }}]}")
List<TestEntity> getTestEntityByIntervalOfExclusion(Integer a1, Integer a2);
4-使用
1-插入/修改
/**
* 插入/修改
*/
@Test
public void insert(){
/**
* dao.insert()
* 传入实体类,若相同id存在则报错
*/
TestEntity testEntity = new TestEntity()
.setAge(110)
.setName("长寿")
.setIsDeleted(false)
.setCreateTime(new Date())
.setId(99L);
TestEntity insert = dao.insert(testEntity);
System.out.println(insert);
/**
* dao.save()
* 相同id存在则修改,否则则插入
* 存在问题:不指定值的属性会被置空
*/
TestEntity save = dao.save(testEntity);
System.out.println(save);
}
2-查询
/**
* 简单查询
*/
@Test
public void simpleQuery(){
//根据id查询,返回optional
Optional<TestEntity> byId = dao.findById(10L);
byId.ifPresent(System.out::println);
//查询所有
List<TestEntity> all = dao.findAll();
//查询所有并传入分页和排序对象
//page 从 0开始,0代表第一页
PageRequest of = PageRequest.of(2, 3);
PageRequest of1 = PageRequest.of(2, 10, Sort.by(Sort.Order.desc("age")));
Page<TestEntity> all1 = dao.findAll(of);
// Page<TestEntity> all2 = dao.findAll(of1);
List<TestEntity> testEntities = all1.toList();
System.out.println(testEntities);
}
public static void main(String[] args) {
PageRequest of = PageRequest.of(2, 3, Sort.by(Sort.Order.desc("age")));
System.out.println(of);
}
/**
* 复杂查询
*/
@Test
public void complexQuery(){
//构建条件匹配对象
TestEntity testEntity = new TestEntity()
.setAge(18)
.setName("张三")
.setIsDeleted(false);
//构建条件匹配器
ExampleMatcher name = ExampleMatcher.matching()
//忽略条件,若不忽略则也会参与条件匹配,会导致无法查询到数据
.withIgnorePaths("age","is_deleted","create_time","_id","_class")
.withMatcher("username", ExampleMatcher.GenericPropertyMatchers.caseSensitive())
.withMatcher("username",item -> item.contains());
//组合匹配器和条件匹配对象
Example<TestEntity> of = Example.of(testEntity, name);
//传入 example 查询条件
List<TestEntity> all = dao.findAll(of);
System.out.println(all);
}
3-删除
/**
* 删除
*/
@Test
public void remove(){
/**
* 使用id删除
* 无返回值,成功失败都无返回值
*/
dao.deleteById(99L);
}
4-使用自定义接口
/**
* 使用注解实现手动编写 mognog 语句
*/
@Test
public void queryAnnoTest(){
TestEntity testEntityById = dao.getTestEntityById(3L);
System.out.println(testEntityById);
List<TestEntity> entities = dao.getAllTestTntityByNameLike("张三");
System.out.println(entities);
List<TestEntity> testEntityByIntervalOfExclusion = dao.getTestEntityByIntervalOfExclusion(20, 60);
System.out.println(testEntityByIntervalOfExclusion);
}
使用 MongoTemplate
1.集合操作
MongoCollection<Document> test_collection = mongoTemplate.createCollection("test_collection");
boolean test_collection1 = mongoTemplate.collectionExists("test_collection");
mongoTemplate.dropCollection("test_collection");
2-查询(find)
1-简单查询
List<TestEntity> all = mongoTemplate.findAll(TestEntity.class);
System.out.println(all);
TestEntity byId = mongoTemplate.findById(1, TestEntity.class);
System.out.println(byId);
TestEntity one = mongoTemplate.findOne(new Query(), TestEntity.class);
System.out.println(one);
2-构建查询对象(Query)
Query query = new Query();
query.with(Sort.by(Sort.Order.desc("id")));
query.skip(10);
query.limit(10);
Criteria name = new Criteria()
.where("name")
.is("张三");
Criteria age = Criteria.where("age")
.gt(18)
.lt(60);
query.addCriteria(name);
query.addCriteria(age);
query.fields()
.include(getFieldName(TestEntity::getAge))
.exclude(getFieldName(TestEntity::getName));
List<TestEntity> entities = mongoTemplate.find(query, TestEntity.class);
3-and 和 or 操作
List<TestEntity> andEntitys = mongoTemplate.find(new Query().addCriteria(
new Criteria()
.andOperator(
Criteria.where("name")
.regex("张"),
Criteria.where("age")
.gte(15)
)
), TestEntity.class);
Query query = new Query();
System.out.println(andEntitys);
List<TestEntity> andEntitys1 = mongoTemplate.find(new Query().addCriteria(
new Criteria()
.where("name")
.regex("张")
.and("age")
.gte(15)
), TestEntity.class);
System.out.println(andEntitys1);
List<TestEntity> test_entity = mongoTemplate.find(new Query(
new Criteria()
.orOperator(
Criteria.where("age")
.lt(3),
Criteria.where("age")
.gt(18)
)
), TestEntity.class, "test_entity");
System.out.println("test_entity" + test_entity);
4-使用原生语句查询
String bson = "{'$and':[{'age':{'$gt':2}},{'age':{'$lt':19}}],'username':/李/}";
BasicQuery basicQuery = new BasicQuery(bson);
basicQuery.with(Sort.by(Sort.Order.asc(getFieldName(TestEntity::getAge))))
.fields()
.include("name");
List<TestEntity> testEntities = mongoTemplate.find(basicQuery, TestEntity.class);
System.out.println(testEntities);
5-统计查询
long count = mongoTemplate.count(
new Query(
Criteria.where("age")
.gt(14)
),
"test_entity");
System.out.println("count->>" + count);
3-新增修改(save)
1-新增
TestEntity save = mongoTemplate.save(new TestEntity());
2-修改
@Test
public void updateDocument(){
Update update = new Update();
update.setOnInsert("id",6);
update.set(getFieldName(TestEntity::getAge),28);
Query query = new Query().addCriteria(Criteria.where(getFieldName(TestEntity::getName)).is("张三"));
UpdateResult upsert = mongoTemplate.upsert(query, update, TestEntity.class);
System.out.println(upsert);
UpdateResult updateFirstResult = mongoTemplate.updateFirst(query, update, TestEntity.class);
UpdateResult updateAllResult = mongoTemplate.updateMulti(query, update, TestEntity.class);
System.out.println("新增时id->>"+updateAllResult.getUpsertedId());
System.out.println("条件匹配行数->>"+updateAllResult.getMatchedCount());
System.out.println("实际修改行数->>"+updateAllResult.getModifiedCount());
}
3-使用原生语句修改
String bson = "{'$set':{'age':20,'isDeleted':false}}";
BasicUpdate basicUpdate = new BasicUpdate(bson);
UpdateResult updateResult = mongoTemplate.updateFirst(
new Query().addCriteria(
Criteria.where(
getFieldName(TestEntity::getName)
).is("张三")
),
basicUpdate,
TestEntity.class
);
System.out.println("新增时id->>"+updateResult.getUpsertedId());
System.out.println("条件匹配行数->>"+updateResult.getMatchedCount());
System.out.println("实际修改行数->>"+updateResult.getModifiedCount());
4-删除
1-删除所有文档
DeleteResult removeA = mongoTemplate.remove(new Query(), TestEntity.class);
DeleteResult removeB = mongoTemplate.remove(new Query(), "test_entity");
long deletedCount = removeA.getDeletedCount();
mongoTemplate.dropCollection(TestEntity.class);
mongoTemplate.dropCollection("collectionName/删除的集合名称");
2-删除指定文档
DeleteResult test_entity = mongoTemplate.remove(new Query(), "test_entity");
System.out.println("删除结果集->>"+test_entity);
System.out.println("受影响的行数->>"+test_entity.getDeletedCount());
5-聚合管道使用
1-基础聚合
Criteria age = Criteria.where("age")
.gt(18)
.lt(100);
MatchOperation match = Aggregation.match(age);
SortOperation sort = Aggregation.sort(Sort.Direction.DESC, "age");
SkipOperation skip = Aggregation.skip(2);
LimitOperation limit = Aggregation.limit(2);
TypedAggregation<TestEntity> testEntityTypedAggregation = TypedAggregation.newAggregation(TestEntity.class, match, sort, skip, limit);
AggregationResults<TestEntity> aggregate = mongoTemplate.aggregate(testEntityTypedAggregation, TestEntity.class);
Document rawResults = aggregate.getRawResults();
List<TestEntity> mappedResults = aggregate.getMappedResults();
System.out.println(mappedResults);
2-多表关联
Criteria age = Criteria.where("age")
.gt(18)
.lt(100);
MatchOperation match = Aggregation.match(age);
SortOperation sort = Aggregation.sort(Sort.Direction.DESC, "age");
SkipOperation skip = Aggregation.skip(2);
LimitOperation limit = Aggregation.limit(2);
TypedAggregation<TestEntity> testEntityTypedAggregation = TypedAggregation.newAggregation(TestEntity.class, match, sort, skip, limit);
AggregationResults<TestEntity> aggregate = mongoTemplate.aggregate(testEntityTypedAggregation, TestEntity.class);
Document rawResults = aggregate.getRawResults();
List<TestEntity> mappedResults = aggregate.getMappedResults();
System.out.println(mappedResults);
工具类
分页工具类(PageSize,PageNum和Limit,Skip转换)
import com.gitee.xiezengcheng.fluent.mongo.reflection.ReflectionUtil;
import com.gitee.xiezengcheng.fluent.mongo.reflection.SerializableFunction;
import org.springframework.data.mongodb.core.query.Query;
@SuppressWarnings("all")
public class PageUtil {
private Integer pageSize = 10;
private Integer pageNumber = 1;
private PageUtil(Integer pageSize, Integer pageNumber) {
if (pageSize <= 0){
pageSize = 10;
}else {
this.pageSize = pageSize;
}
if (pageNumber < 1){
pageNumber = 1;
}else {
this.pageNumber = pageNumber;
}
}
private PageUtil() {}
public static PageUtil build(){
return new PageUtil();
}
public static PageUtil build(Integer pageSize, Integer pageNumber){
return new PageUtil(pageSize,pageNumber);
}
public Integer getLimit() {
return pageSize;
}
public Integer getSkip() {
return (pageNumber - 1) * pageSize;
}
public PageUtil setPageSize(Integer pageSize) {
this.pageSize = pageSize;
return this;
}
public PageUtil setPageNumber(Integer pageNumber) {
this.pageNumber = pageNumber;
return this;
}
public static Query buildMongoQuery(Query query, Integer pageSize, Integer pageNumber){
return query.limit(pageSize)
.skip((pageNumber - 1) * pageSize);
}
public static Query buildMongoQuery(Integer pageSize, Integer pageNumber){
return new Query().limit(pageSize)
.skip((pageNumber - 1) * pageSize);
}
public Query buildMongoQuery(Query query){
return query.limit(getLimit())
.skip(getSkip());
}
public Query buildMongoQuery(){
return new Query().limit(getLimit())
.skip(getSkip());
}
public static<T,R> String getFieldName(SerializableFunction<T, R> fun){
return ReflectionUtil.getFieldName(fun);
}
}
管道聚合工具类
import com.gitee.xiezengcheng.fluent.mongo.reflection.SerializableFunction;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.query.CriteriaDefinition;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import static com.gitee.xiezengcheng.fluent.mongo.reflection.ReflectionUtil.getFieldName;
import static com.gitee.xiezengcheng.fluent.mongo.reflection.ReflectionUtil.getField;
@SuppressWarnings("all")
public class AggregationUtil {
private AggregationUtil() {
}
private ArrayList<AggregationOperation> list = new ArrayList<AggregationOperation>();
public static AggregationUtil build() {
return new AggregationUtil();
}
public ArrayList<AggregationOperation> getOperations(){
return this.list;
}
public <T> TypedAggregation<T> buildTypedAggregation(Class<T> type) {
TypedAggregation<T> tTypedAggregation = TypedAggregation.newAggregation(type, list);
return tTypedAggregation;
}
public AggregationUtil project(String... strings) {
if (strings != null && strings.length > 0) {
ProjectionOperation project = Aggregation.project(strings);
list.add(project);
}
return this;
}
public <T, R> AggregationUtil project(SerializableFunction<T, R>... funs) {
if (funs != null && funs.length > 0) {
ArrayList<String> stringList = new ArrayList<>();
for (SerializableFunction<T, R> fun : funs) {
String fieldName = getField(fun).getName();
System.out.println(fieldName);
stringList.add(fieldName);
}
String[] objects = new String[funs.length];
for (int i = 0; i < stringList.size(); i++) {
objects[i] = stringList.get(i);
}
ProjectionOperation project = Aggregation.project(objects);
list.add(project);
}
return this;
}
public AggregationUtil match(CriteriaDefinition... criteriaDefinition) {
if (criteriaDefinition != null && criteriaDefinition.length > 0) {
for (CriteriaDefinition definition : criteriaDefinition) {
list.add(Aggregation.match(definition));
}
}
return this;
}
public AggregationUtil count(String fieldName) {
CountOperation.CountOperationBuilder count = Aggregation.count();
boolean empty = StringUtils.isEmpty(fieldName);
if (empty) {
fieldName = "countField";
}
CountOperation as = count.as(fieldName);
list.add(as);
return this;
}
public <T, R> AggregationUtil count(SerializableFunction<T, R> fun) {
return count(getFieldName(fun));
}
public AggregationUtil group(String... fields) {
if (fields != null && fields.length > 0) {
GroupOperation group = Aggregation.group(fields);
list.add(group);
}
return this;
}
public <T, R> AggregationUtil group(SerializableFunction<T, R>... fields) {
if (fields != null && fields.length > 0) {
ArrayList<String> stringList = new ArrayList<>();
for (SerializableFunction<T, R> fun : fields) {
String fieldName = getFieldName(fun);
stringList.add(fieldName);
}
String[] objects = (String[]) stringList.toArray();
GroupOperation group = Aggregation.group(objects);
list.add(group);
}
return this;
}
public AggregationUtil unwind(String... fields) {
unwind(false, fields);
return this;
}
public <T, R> AggregationUtil unwind(SerializableFunction<T, R>... fields) {
unwind(false, fields);
return this;
}
public AggregationUtil unwind(boolean preserveNullAndEmptyArrays, String... fields) {
if (fields != null && fields.length > 0) {
for (String field : fields) {
list.add(Aggregation.unwind(field, preserveNullAndEmptyArrays));
}
}
return this;
}
public <T, R> AggregationUtil unwind(boolean preserveNullAndEmptyArrays, SerializableFunction<T, R>... fields) {
if (fields != null && fields.length > 0) {
for (SerializableFunction<T, R> field : fields) {
list.add(Aggregation.unwind(getFieldName(field), preserveNullAndEmptyArrays));
}
}
return this;
}
public AggregationUtil limit(long maxElements) {
if (maxElements < 0) {
maxElements = 10;
}
LimitOperation limit = Aggregation.limit(maxElements);
list.add(limit);
return this;
}
public AggregationUtil skip(long elementsToSkip) {
if (elementsToSkip < 0) {
elementsToSkip = 0;
}
SkipOperation skip = Aggregation.skip(elementsToSkip);
list.add(skip);
return this;
}
public AggregationUtil sort(Sort sort) {
SortOperation sortOperation = Aggregation.sort(sort);
list.add(sortOperation);
return this;
}
public AggregationUtil lookup(String from, String localField, String foreignField, String as) {
LookupOperation lookup = Aggregation.lookup(from, localField, foreignField, as);
list.add(lookup);
return this;
}
public <T, R> AggregationUtil lookup(Class fromClass, SerializableFunction<T, R> localField, SerializableFunction<T, R> foreignField, String as) throws Exception {
return lookup(getDocumentAnnoValue(fromClass), getFieldName(localField), getFieldName(foreignField), as);
}
public static String getDocumentAnnoValue(Class zClass) throws Exception {
boolean annotationPresent = zClass.isAnnotationPresent(Document.class);
if (annotationPresent) {
Document annotation = (Document) zClass.getAnnotation(Document.class);
String collection = annotation.collection();
String value = annotation.value();
String collectionName = "";
if (!isEmpty(collection) && !isEmpty(value)) {
if (collection.equals(value)) {
collectionName = value;
}
} else if (isEmpty(collection) && !isEmpty(value)) {
collectionName = value;
} else if (!isEmpty(collection) && isEmpty(value)) {
collectionName = collection;
}
return collectionName;
}
throw new Exception("类 \"" + zClass.getName() + "\" 没有使用 MongoDB @Document 注解标识集合名称,无法获取集合名");
}
private static boolean isEmpty(String str) {
return str == null || "".equals(str);
}
}