1. 加入依赖
<!--mongodb-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
2. 连接配置
spring:
data:
mongodb:
host: localhost #同127.0.0.1
port: 27017
database: test #指定操作的数据库
3. 对Monodb进行查询
详细代码见附录。
3.1 简单查询
数据准备:
db.stus.insert([
{ "_id" : ObjectId("5e64bf9a2a16affa306b8b93"), "name" : "数组1", "age" : "18","gender" : "男","scope" : 77.0},
{"_id" : ObjectId("5e64cc2b6ef8da42f1854b11"), "name" : "数组2","age" : "13", "gender" : "女","scope" : 89},
{ "_id" : ObjectId("5e663e7379bbd40eb81de8eb"),"name" : "数组3","age" : "13","gender" : "男","scope" : 60},
{"_id" : ObjectId("5e6648d179bbd40eb81de8ee"),"name" : "数组4","age" : "14","gender" : "男","scope" : 59},
{"_id" : ObjectId("5e6648d479bbd40eb81de8f0"),"name" : "数组5","age" : "18","gender" : "男","scope" : 68},
{"_id" : ObjectId("5e6648d879bbd40eb81de8f1"),"name" : "数组6","age" : "24","gender" : "男","scope" : 56},
{"_id" : ObjectId("5e6648d979bbd40eb81de8f2"),"name" : "数组7","age" : "25","gender" : "女", "scope" : 90},
{ "_id" : ObjectId("5e6648d979bbd40eb81de8f3"),"name" : "数组8","age" : "24","gender" : "男","scope" : 98},
{ "_id" : ObjectId("5e6648d979bbd40eb81de8f4"),"name" : "数组9", "age" : "18","gender" : "男","scope" : 45},
{ "_id" : ObjectId("5e6648d979bbd40eb81de8f5"),"name" : "数组10", "age" : "14", "gender" : "女", "scope" : 67}
]);
1. 对数据进行简单查询:
/**
* Criteria—条件
* Sort—排序
* Query—查询语句
* findOne(Query query, Class<T> entityClass)会获取传入的entityClass名的`简单类名`去寻找集合。
* findOne(Query query, Class<T> entityClass, String collectionName) 也可以使用该方法指定集合
*/
//常规查询操作
public static void find() {
//排序(降序处理)
Sort sort = new Sort(Sort.Direction.DESC, "scope");
//配置查询的条件
Query query = new Query(Criteria.where("gender").is("男")). //先$match筛选
with(sort). //在$sort排序
limit(1); //在$limit截取
Student student = mongoTemplate.findOne(query, Student.class, "stus");
log.info("MongoDB最终输出:" + JSON.toJSONString(student));
}
最终返回结果:
MongoDB最终输出:{"age":"24","gender":"男","id":"5e6648d979bbd40eb81de8f3","name":"数组8","scope":"98"}
2. 对数据进行查询
/**
* scope字段大于60小于90
*/
public static void find2() {
Query query = new Query(Criteria.where("scope").gt(60).lt(90));
List<Student> students = mongoTemplate.find(query, Student.class, "stus");
log.info(JSON.toJSONString(students));
}
最终返回结果:
[{"age":"18","gender":"男","id":"5e64bf9a2a16affa306b8b93","name":"数组1","scope":"77.0"},
{"age":"13","gender":"女","id":"5e64cc2b6ef8da42f1854b11","name":"数组2","scope":"89"},
{"age":"18","gender":"男","id":"5e6648d479bbd40eb81de8f0","name":"数组5","scope":"68"},
{"age":"14","gender":"女","id":"5e6648d979bbd40eb81de8f5","name":"数组10","scope":"67"}]
3.2 聚合查询
public class Aggregation {
public static Aggregation newAggregation(AggregationOperation... operations) {
return new Aggregation(operations);
}
public static <T> TypedAggregation<T> newAggregation(Class<T> type, AggregationOperation... operations) {
return new TypedAggregation<T>(type, operations);
}
public static <T> TypedAggregation<T> newAggregation(Class<T> type, List<? extends AggregationOperation> operations) {
return newAggregation(type, operations.toArray(new AggregationOperation[operations.size()]));
}
public static Aggregation newAggregation(List<? extends AggregationOperation> operations) {
return newAggregation(operations.toArray(new AggregationOperation[operations.size()]));
}
}
聚合函数的原生语法:
db.collection.aggregate(pipeline,options);
-
pipeline
一系列的聚合操作,可以对文档进行一连串的处理,包括筛选(match)、映射(project)、分组(group)、排序(sort)、限制(limit)、跳跃(skip)
。 -
options
(可选)控制聚合函数的执行的一些参数。
而org.springframework.data.mongodb.core.aggregation.Aggregation
提供了上述4个newAggregation
方法,来接收pipeline
数组。即AggregationOperation
集合。
案例1:
public static void find3() {
TypedAggregation<Student> typedAggregation = Aggregation.newAggregation(Student.class,
Aggregation.match(Criteria.where("scope").gt(60).lt(90)) //相当于where操作
);
//打印出原生的聚合命令
log.info("输出聚合对象{}", typedAggregation.toString());
AggregationResults<BasicDBObject> aggregate = mongoTemplate.aggregate(typedAggregation, "stus", BasicDBObject.class);
//输出结果
List<BasicDBObject> mappedResults = aggregate.getMappedResults();
log.info("输出结果{}", mappedResults.toString());
}
输出结果:
输出聚合对象{ "aggregate" : "__collection__", "pipeline" : [{ "$match" : { "scope" : { "$gt" : 60, "$lt" : 90 } } }] }
输出结果[Document{{_id=5e64bf9a2a16affa306b8b93, name=数组1, age=18, gender=男, scope=77.0}},
Document{{_id=5e64cc2b6ef8da42f1854b11, name=数组2, age=13, gender=女, scope=89}},
Document{{_id=5e6648d479bbd40eb81de8f0, name=数组5, age=18, gender=男, scope=68}},
Document{{_id=5e6648d979bbd40eb81de8f5, name=数组10, age=14, gender=女, scope=67}}]
注:上述日志输出的“聚合对象”是原生的Mongodb语句,可进行参考
。
案例2:
数据准备
db.items.insert([
{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-03-01T08:00:00Z") },
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-03-01T09:00:00Z") },
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-03-15T09:00:00Z") },
{ "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "date" : ISODate("2014-04-04T11:21:39.736Z") },
{ "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-04-04T21:23:13.331Z") }
]);
public static void find4() {
List<Double> collection = new ArrayList<>();
collection.add(10.0);
collection.add(5.0);
TypedAggregation<Items> itemsTypedAggregation = Aggregation.newAggregation(Items.class,
Aggregation.match(Criteria.where("price").in(collection)),
Aggregation.project("date").andExpression("month(date)").as("month"),
Aggregation.group("month").count().as("num"),
Aggregation.project("num").and("month").previousOperation()
);
//打印表达式
log.info("聚合表达式:{}",itemsTypedAggregation.toString());
AggregationResults<BasicDBObject> result = mongoTemplate.aggregate(itemsTypedAggregation, BasicDBObject.class);
//打印数据
log.info(JSON.toJSONString(result.getMappedResults()));
}
最终会在Mongodb中执行如下代码:
db.items.aggregate(
[{ "$match" : { "price" : { "$in" : [10.0, 5.0] } } }, //使用in去筛选
{ "$project" : { "date" : 1, "month" : { "$month" : "$date" } } }, //映射数据
{ "$group" : { "_id" : "$month", "num" : { "$sum" : 1 } } }, //以映射的数据分组,在进行统计
{ "$project" : { "num" : 1, "_id" : 0, "month" : "$_id" } }] //打印统计数据和month月份信息
)
最终结果:
[{"num":2,"month":3},{"num":2,"month":4}]
案例3:group中使用表达式进行分组
按date的月份、日期、年份对文档进行分组,并计算total price和average quantity,并汇总各文档的数量。
image.png 错误示例.png正确示例:
public static void find6() {
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.project("quantity")
.andExpression("year(date)").as("year")
.andExpression("month(date)").as("month")
.andExpression("dayOfMonth(date)").as("day")
.andExpression("price * quantity").as("grossPrice"),
// .and("quantity"), 等效于project("quantity")
Aggregation.group("month", "year", "day")
.sum("grossPrice").as("totalPrice")
.avg("quantity").as("averageQuantity")
.count().as("count")
);
log.info("聚合表达式:{}", aggregation);
AggregationResults<BasicDBObject> items = mongoTemplate.aggregate(aggregation, "items", BasicDBObject.class);
log.info(JSON.toJSONString(items.getMappedResults()));
}
输出结果:
[{"month":4,"year":2014,"day":4,"totalPrice":200,"averageQuantity":15,"count":2},
{"month":3,"year":2014,"day":15,"totalPrice":50,"averageQuantity":10,"count":1},
{"month":3,"year":2014,"day":1,"totalPrice":40,"averageQuantity":1.5,"count":2}]
注意:使用group分组后,_id字段是分组字段!
4. CURD操作
@Service
@Slf4j
public class MongoDbService {
@Autowired
private MongoTemplate mongoTemplate;
public String saveObj(Book book) {
book.setCreateTime(new Date());
book.setUpdateTime(new Date());
Book save = mongoTemplate.save(book);
return "添加成功";
}
public List<Book> findAll() {
return mongoTemplate.findAll(Book.class);
}
public Book getBookById(String id) {
Query query = new Query(Criteria.where("_id").is(id));
return mongoTemplate.findOne(query, Book.class);
}
public Book getBookByName(String name) {
Query query = new Query(Criteria.where("name").is(name));
return mongoTemplate.findOne(query, Book.class);
}
public String updateBook(Book book) {
Query query = new Query(Criteria.where("_id").is(book.getId()));
Update update = new Update().
set("publish", book.getPublish()).
set("info", book.getInfo()).
set("updateTime", new Date());
//更新查询返回结果集的第一条
UpdateResult updateResult = mongoTemplate.updateFirst(query, update, Book.class);
log.info(JSON.toJSONString(updateResult));
return "success";
// return updateResult.getModifiedCount();
}
//删除对象
public String deleteBook(Book book) {
DeleteResult remove = mongoTemplate.remove(book);
log.info(JSON.toJSONString(remove));
return "success";
}
//根据id去删除
public String deleteBookById(String id) {
Book book = getBookById(id);
return deleteBook(book);
}
}
@RestController
@Slf4j
public class BaseController {
@Autowired
private MongoDbService mongoDbService;
@PostMapping("/mongo/save")
public String saveObj(@RequestBody Book book) {return mongoDbService.saveObj(book);}
@GetMapping("/mongo/findAll")
public List<Book> findAll() {return mongoDbService.findAll();}
@GetMapping("/mongo/findOne")
public Book findOne(@RequestParam String id) {return mongoDbService.getBookById(id);}
@GetMapping("/mongo/findOneByName")
public Book findOneByName(@RequestParam String name) {return mongoDbService.getBookByName(name);}
@PostMapping("/mongo/update")
public String update(@RequestBody Book book) {return mongoDbService.updateBook(book);}
@PostMapping("/mongo/delOne")
public String delOne(@RequestBody Book book) {return mongoDbService.deleteBook(book);}
@GetMapping("/mongo/delById")
public String delById(@RequestParam String id) {return mongoDbService.deleteBookById(id);}
}
@Data
public class Book {
private String id;
//价格
private Integer price;
//书名
private String name;
//简介
private String info;
//出版社
private String publish;
//创建时间
private Date createTime;
//修改时间
private Date updateTime;
}
附录
使用如下代码去获取mongoTemplate
对象,可以将对Mongodb的操作整合为一个工具类方法,直接通过静态方法便可以完成调用。
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
log.info("ApplicationContextAware初始化完毕");
SpringContextUtil.context=applicationContext;
}
public static <T> T getBean(String name, Class<T> requiredType){
return context.getBean(name, requiredType);
}
public static <T> T getBean(Class<T> requiredType){
return context.getBean(requiredType);
}
/**
* 获取beanName数组
* @return
*/
public static String[] getBeanNamesForType(Class<?> clazz){
return context.getBeanNamesForType(clazz);
}
}
package com.tellme.config.mongodb;
import com.alibaba.fastjson.JSON;
import com.mongodb.BasicDBObject;
import com.tellme.config.context.SpringContextUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import java.util.Iterator;
import java.util.List;
@Slf4j
public class MongodbUtils {
//在Spring容器中获取Bean
private static MongoTemplate mongoTemplate = SpringContextUtil.getBean("mongoTemplate", MongoTemplate.class);
@Data
private class Items {
private String id;
private String item;
private double price;
private double quantity;
private Date date;
}
@Data
private class Student {
private String id;
private String name;
private String age;
private String gender;
private String scope;
}
}
推荐阅读
MongoDB mongoTemplate查询条作组合例子(超多案例)
网友评论