共计 12633 个字符,预计需要花费 32 分钟才能阅读完成。
- Java mongoTemplate
应用 mongoTemplate 表白 mongo shell 表达式。 - 应用 spring boot 集成 mongo,而后间接跑 test 实操
蕴含,$group,$project 等操作
package com.example.springboot; | |
import lombok.Builder; | |
import lombok.Getter; | |
import lombok.Setter; | |
import lombok.ToString; | |
import org.aspectj.lang.annotation.Before; | |
import org.assertj.core.util.Lists; | |
import org.junit.jupiter.api.BeforeAll; | |
import org.junit.jupiter.api.BeforeEach; | |
import org.junit.jupiter.api.Test; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.test.context.SpringBootTest; | |
import org.springframework.data.annotation.Id; | |
import org.springframework.data.domain.Sort; | |
import org.springframework.data.mongodb.core.BulkOperations; | |
import org.springframework.data.mongodb.core.MongoTemplate; | |
import org.springframework.data.mongodb.core.aggregation.*; | |
import org.springframework.data.mongodb.core.mapping.Document; | |
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.data.mongodb.core.query.UpdateDefinition; | |
import org.springframework.data.util.Pair; | |
import org.springframework.util.StringUtils; | |
import javax.swing.*; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.regex.Pattern; | |
import java.util.stream.Collectors; | |
import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregationOptions; | |
/** | |
* @see com.example.springboot.SpringbootApplicationTests#testProject() | |
*/ | |
@SpringBootTest | |
class SpringbootApplicationTests { | |
@Autowired | |
private MongoTemplate mongoTemplate; | |
@Test | |
void contextLoads() {} | |
/** | |
* 初始化 student 数据 | |
*/ | |
@Test | |
public void setupData(){Student student = Student.builder() | |
.id("1").name("张三").age(15).chinese(90).maths(95).physics(93).chemistry(100).biology(99).english(98).build(); | |
Student student1 = Student.builder() | |
.id("2").name("李四").age(18).chinese(80).maths(90).physics(93).chemistry(88).biology(93).english(83).build(); | |
Student student2 = Student.builder() | |
.id("3").name("王五").age(16).chinese(72).maths(80).physics(84).chemistry(77).biology(79).english(72).build(); | |
Student student3 = Student.builder() | |
.id("4").name("王小二").age(20).chinese(72).maths(80).physics(84).chemistry(77).biology(79).english(72).build(); | |
Student student4 = Student.builder() | |
.id("5").name("jim").age(20).chinese(72).maths(80).physics(84).chemistry(77).biology(79).english(79).build(); | |
List<Student> students = Lists.newArrayList(student,student1, student2,student3, student4); | |
BulkOperations bulkOperations = | |
mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, Student.COLLECTION); | |
bulkOperations.insert(students); | |
bulkOperations.execute();} | |
/** | |
* 初始化书籍数据 | |
*/ | |
@Test | |
public void setupBooksData(){Book apue = Book.builder().id("1").title("apue").author("stevens").type("computer").copies(8).build(); | |
Book mysqlInAction = Book.builder().id("2").title("mysql in action").author("lee").type("computer").copies(10).build(); | |
Book redisInAction = Book.builder().id("3").title("redis in action").author("lee").type("computer").copies(5).build(); | |
Book englishABC = Book.builder().id("4").title("english A B C").author("li lei").type("english").copies(15).build(); | |
Book toefl = Book.builder().id("5").title("toefl").author("li lei").type("english").copies(10).build(); | |
Book chinese = Book.builder().id("6").title("chinese A B C").author("zhang san").type("chinese").copies(12).build(); | |
List<Book> students = Lists.newArrayList(apue, mysqlInAction, redisInAction, englishABC, toefl, chinese); | |
BulkOperations bulkOperations = | |
mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, Book.COLLECTION); | |
bulkOperations.insert(students); | |
bulkOperations.execute();} | |
@Test | |
public void insertOneStudent(){Student student3 = Student.builder() | |
.id("7").name("jeff").age(19).chinese(73).maths(80).physics(84).chemistry(77).biology(79).english(72).build(); | |
mongoTemplate.insert(student3); | |
} | |
/** | |
* 数据中没有则保留,有这更新 | |
*/ | |
@Test | |
public void saveOneStudent(){Student student3 = Student.builder() | |
.id("7").name("jeff").age(100).chinese(73).maths(80).physics(84).chemistry(77).biology(79).english(72).build(); | |
mongoTemplate.save(student3); | |
} | |
@Test | |
public void batchSave(){// 见数据初始化处} | |
/** | |
* update 批量更新,*/ | |
@Test | |
public void testBatchUpdate(){List<Pair<Query, Update>> updates = new ArrayList<>(); | |
for (int i = 0; i < 5; i ++){Query query = new Query(); | |
Criteria criteria = new Criteria().and("_id").is(i+ ""); | |
query.addCriteria(criteria); | |
Update update = Update.update("age", i); | |
updates.add(Pair.of(query, update)); | |
} | |
BulkOperations bulkOperations = | |
mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "student"); | |
bulkOperations.updateMulti(updates); | |
bulkOperations.execute();} | |
/** | |
* 将查问进去的后果对立批改。* mongoTemplate.upsert 办法,如果不存在,则新建一条记录。存在则更新,十分有用。*/ | |
@Test | |
public void testUpdate(){Query query = new Query(); | |
Criteria criteria = new Criteria().and("age").is(18); | |
query.addCriteria(criteria); | |
UpdateDefinition update = Update.update("english", 99); | |
mongoTemplate.updateMulti(query, update, "student"); | |
} | |
/** | |
* find $in | |
*/ | |
@Test | |
public void testFindByIn(){Query query = new Query(); | |
Criteria criteria = new Criteria().and("age").in(18,19,20); | |
query.addCriteria(criteria); | |
// query.withHint("age"); // 举荐 mongo 应用索引 | |
query.skip(1); | |
query.limit(10); | |
query.with(Sort.by(Sort.Direction.DESC, "age")); | |
String qString = query.getQueryObject().toString(); | |
System.out.println(qString); | |
List<Student> students = mongoTemplate.find(query, Student.class); | |
System.out.println(students); | |
} | |
/** | |
* 正则 | |
* db.student.find({name : /Jim/i}); 都是疏忽大小写的 | |
* db.student.find({name : {$regex: "Jim", $options: "$i"}}); | |
*/ | |
@Test | |
public void testFindByRegex(){ | |
String regexStr = "^JI"; | |
// Criteria criteria = new Criteria().and("name").regex(regexStr, "I"); // I 疏忽大小写 | |
Pattern pattern = Pattern.compile(regexStr, Pattern.CASE_INSENSITIVE); | |
Criteria criteria = new Criteria().and("name").regex(pattern); | |
Query query = Query.query(criteria); | |
List<Student> students = mongoTemplate.find(query, Student.class); | |
System.out.println(students); | |
} | |
/** | |
* group author. | |
* "pipeline" : [{"$match" : {}}, {"$group" : { "_id" : "$author", "copiesTotal" : { "$sum" : "$copies"}, "copiesMax" : {"$max" : "$copies"}, "avg" : {"$avg" : "$copies"}}}] | |
*/ | |
@Test | |
public void TestGroup() {List<AggregationOperation> operations = Lists.newArrayList(); | |
Criteria criteria = new Criteria(); | |
// todo 减少过滤条件 | |
operations.add(Aggregation.match(criteria)); | |
GroupOperation groupOperation = new GroupOperation(Fields.fields("author")). | |
sum("copies").as("copiesTotal"). | |
max("copies").as("copiesMax"). | |
avg("copies").as("avg"); | |
operations.add(groupOperation); | |
Aggregation aggregation = Aggregation.newAggregation(operations) | |
.withOptions(newAggregationOptions().allowDiskUse(true).build()); | |
AggregationResults<Map> aggregationResults = | |
mongoTemplate.aggregate(aggregation, "book", Map.class); | |
System.out.println(aggregationResults.getMappedResults()); | |
} | |
/** | |
* $group 字段为 null 时,去所有 $match 匹配的文档都为一个分组。* $push 将字段退出某个数组,所有 group 的分组中的字段都退出 | |
* $addToSet 和 push 相比会去重 | |
* | |
* "pipeline" : [{"$match" : {}}, {"$group" : { "_id" : null, "authurs" : { "$push" : "$author"}}}, {"$project" : { "_id" : 0}}] | |
* "pipeline" : [{"$match" : {}}, {"$group" : { "_id" : null, "authors" : { "$push" : "$author"}, "uniqueAuthors" : {"$addToSet" : "$author"}}}, {"$project" : { "_id" : 0}}] | |
*/ | |
@Test | |
public void testPush(){List<AggregationOperation> operations = Lists.newArrayList(); | |
Criteria criteria = new Criteria(); | |
operations.add(Aggregation.match(criteria)); | |
GroupOperation groupOperation = Aggregation.group(). | |
push("author").as("authors") | |
.addToSet("author").as("uniqueAuthors"); | |
operations.add(groupOperation); | |
ProjectionOperation projectionOperation = Aggregation.project().andExclude("_id"); | |
operations.add(projectionOperation); | |
Aggregation aggregation = Aggregation.newAggregation(operations) | |
.withOptions(newAggregationOptions().allowDiskUse(true).build()); | |
AggregationResults<Map> aggregationResults = | |
mongoTemplate.aggregate(aggregation, "book", Map.class); | |
System.out.println(aggregationResults.getMappedResults()); | |
} | |
/** | |
* $unwind 根据某个字段数组拆分成独自的文档。* "pipeline" : [{"$match" : {}}, {"$group" : { "_id" : null, "authors" : { "$push" : "$author"}, "uniqueAuthors" : {"$addToSet" : "$author"}}}, {"$project" : { "_id" : 0}}, {"$unwind" : "$authors"}] | |
*/ | |
@Test | |
public void testUnwind(){List<AggregationOperation> operations = Lists.newArrayList(); | |
Criteria criteria = new Criteria(); | |
operations.add(Aggregation.match(criteria)); | |
GroupOperation groupOperation = Aggregation.group(). | |
push("author").as("authors") | |
.addToSet("author").as("uniqueAuthors"); | |
operations.add(groupOperation); | |
ProjectionOperation projectionOperation = Aggregation.project().andExclude("_id"); | |
operations.add(projectionOperation); | |
operations.add(Aggregation.unwind("authors")); | |
Aggregation aggregation = Aggregation.newAggregation(operations) | |
.withOptions(newAggregationOptions().allowDiskUse(true).build()); | |
AggregationResults<Map> aggregationResults = | |
mongoTemplate.aggregate(aggregation, "book", Map.class); | |
System.out.println(aggregationResults.getMappedResults()); | |
} | |
/** | |
* project 解决 english 和 maths 之和,并不输入 id 字段。* "pipeline" : [{"$match" : {}}, {"$project" : { "ts" : { "$add" : ["$english", "$maths"]}, "_id" : 0}}] | |
*/ | |
@Test | |
public void testProject(){List<AggregationOperation> operations = Lists.newArrayList(); | |
Criteria criteria = new Criteria(); | |
operations.add(Aggregation.match(criteria)); | |
ProjectionOperation projectionOperation = new ProjectionOperation(); | |
Fields fields = Fields.fields("student"); | |
projectionOperation.andInclude(fields); | |
projectionOperation = Aggregation.project().and("english").plus("maths").as("ts").andExclude("_id"); | |
operations.add(projectionOperation); | |
Aggregation aggregation = Aggregation.newAggregation(operations) | |
.withOptions(newAggregationOptions().allowDiskUse(true).build()); | |
AggregationResults<Map> aggregationResults = | |
mongoTemplate.aggregate(aggregation, "student", Map.class); | |
System.out.println(aggregationResults.getMappedResults()); | |
} | |
/** | |
* project 输入指定字段,排除其余字段 | |
* "pipeline" : [{"$match" : {}}, {"$project" : { "name" : 1, "english" : 1, "maths" : 1, "chinese" : 1, "_id" : 0}}] | |
*/ | |
@Test | |
public void testProjectField(){List<AggregationOperation> operations = Lists.newArrayList(); | |
Criteria criteria = new Criteria(); | |
operations.add(Aggregation.match(criteria)); | |
ProjectionOperation projectionOperation = new ProjectionOperation(); | |
Fields fields = Fields.fields("name", "english", "maths", "chinese"); | |
projectionOperation = projectionOperation.andInclude(fields).andExclude("_id"); // Aggregation.project(fields).andExclude("_id"); | |
operations.add(projectionOperation); | |
Aggregation aggregation = Aggregation.newAggregation(operations) | |
.withOptions(newAggregationOptions().allowDiskUse(true).build()); | |
AggregationResults<Map> aggregationResults = | |
mongoTemplate.aggregate(aggregation, "student", Map.class); | |
System.out.println(aggregationResults.getMappedResults()); | |
} | |
/** | |
* 统计学生几门课的总分。* 存在问题,如果一个学生的某个课程分数为 null,或者活没有该字段,则统计的 total 为 null. | |
* "pipeline" : [{"$match" : {}}, {"$project" : { "total" : { "$add" : ["$english", "$maths", "$chinese"]}}}] | |
*/ | |
@Test | |
public void testAggregate(){List<AggregationOperation> operations = Lists.newArrayList(); | |
Criteria criteria = new Criteria(); | |
operations.add(Aggregation.match(criteria)); | |
ProjectionOperation projectionOperation; | |
AggregationExpression aggregationExpression = ArithmeticOperators.Add.valueOf("english") | |
.add("maths") | |
.add("chinese"); | |
projectionOperation = Aggregation.project().and(aggregationExpression).as("total"); | |
operations.add(projectionOperation); | |
Aggregation aggregation1 = Aggregation.newAggregation(operations) | |
.withOptions(newAggregationOptions().allowDiskUse(true).build()); | |
AggregationResults<Map> aggregationResults1 = | |
mongoTemplate.aggregate(aggregation1, "student", Map.class); | |
System.out.println(aggregationResults1.getMappedResults()); | |
} | |
/** | |
* 怎么多个 $or 一起操作。* "pipeline" : [{"$match" : { "name" : "张三", "$or" : [{ "maths" : { "$gte" : 90}}, {"english" : { "$gte" : 90}}, {"chinese" : { "$gte" : 90}}]}}] | |
*/ | |
@Test | |
public void testOrOperation(){List<AggregationOperation> operations = Lists.newArrayList(); | |
Criteria criteria = new Criteria(); | |
criteria = criteria.and("name").is("张三"); | |
Criteria criteria1 = new Criteria().and("maths").gte(90); | |
Criteria criteria2 = new Criteria().and("english").gte(90); | |
Criteria criteria3 = new Criteria().and("chinese").gte(90); | |
criteria = criteria.orOperator(criteria1, criteria2, criteria3); | |
operations.add(Aggregation.match(criteria)); | |
Aggregation aggregation = Aggregation.newAggregation(operations).withOptions(newAggregationOptions().allowDiskUse(true).build()); | |
AggregationResults<Student> results = mongoTemplate.aggregate(aggregation, "student", Student.class); | |
System.out.println(results.getMappedResults()); | |
} | |
@Setter | |
@Getter | |
@ToString | |
@Document(Student.COLLECTION) | |
@Builder | |
static class Student{ | |
public static final String COLLECTION = "student"; | |
public static final String MATHS = "maths"; | |
public static final String CHINESE = "chinese"; | |
public static final String ENGLISH = "english"; | |
public static final String PHYSICS = "physics"; | |
public static final String CHEMISTRY = "chemistry"; | |
public static final String BIOLOGY = "biology"; | |
@Id | |
private String id; | |
private String name; | |
private int age; | |
private int maths; | |
private int chinese; | |
private int english; | |
private int physics; | |
private int chemistry; | |
private int biology; | |
} | |
@Setter | |
@Getter | |
@ToString | |
@Document(Book.COLLECTION) | |
@Builder | |
static class Book { | |
public static final String COLLECTION = "book"; | |
@Id | |
private String id; | |
private String title; | |
private String author; | |
private int copies; // 库存数 | |
private String type; | |
} | |
} |
正文完