SpringBoot2.x集成Mongodb

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中使用表达式进行分组

Mongodb(2)—聚合操作(1)原生命令

按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查询条作组合例子(超多案例)

按时间进行分组

历史文章

win7下安装mongodb4.2.3及可视化工具

Mongodb(1)—基本CRUD操作

Mongodb(2)—聚合操作(1)原生命令

SpringBoot2.x集成Mongodb

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容