Mongodb的基本使用及对接多数据源

mongodb介绍

MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是可以应用于各种规模的企业、各个行业以及各类应用程序的开源数据库。基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种。


MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。


MongoDB是一个文档数据库。这里对比RDBMS来介绍Mongodb。


传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成,MongoDB是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。MongoDB的collection对应关系型数据库里的表,但是集合中没有列、行和关系概念


1、基本概念

1.1、数据库

在Mongodb中,db表示数据库,对应RDBMS的数据库。

'show dbs'
可以查看所有数据库
'use 数据库名称'
表示使用指定数据库

1.2、集合

集合Collections对应 RDBMS的表

'show collections'
可以查看当前db下所有集合

1.3、文档

文档对应RDBMS的表中的数据

db.'集合名称'.find();
表示查询当前集合下所有文档数据。其中文档是以BSON进行存储,BSON是一种二进制序列化格式,用于在MongoDB中存储文档和进行远程过程调用。参考BSON介绍

2、特性

2.1、高性能

  • 对嵌入式数据模型的支持减少了数据库系统上的I / O操作
  • 索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键

2.2、丰富的查询语言

  • MongoDB支持丰富的查询语言以支持读写操作(CRUD)
  • 数据聚合
  • 文本搜索和地理空间查询

2.3、高可用

  • MongoDB的复制工具(称为副本集)提供 自动故障转移 和 数据冗余。副本集是一组维护相同数据集合的 mongod实例,提供了冗余和提高了数据可用性。

2.4、水平拓展

  • MongoDB提供水平可伸缩性作为其核心 功能的一部分:数据分片切割将数据分布在一个集群的机器上。
  • 从3.4开始,MongoDB支持基于分片键创建数据区域。在平衡群集中,MongoDB仅将区域覆盖的读写定向到区域内的那些分片。

2.5、支持多种存储引擎

  • WiredTiger存储引擎(包括对静态加密的支持 )
  • 内存存储引擎
  • PS: MongoDB提供可插拔的存储引擎API,允许第三方为MongoDB开发存储引擎

3、mongodb基本命令使用

使用mongodb自带的mongodb Shell来学习mongodb提供的基本CRUD操作

3.1、命令使用说明

mongo --host 127.0.0.1 --port 27017 // 使用命令连接mongodb并使用mongodb Shell

show dbs //查询所有数据库

use mytest //使用指定的数据库

db.myCollection01.insertOne( {x : 1} ); //创建文档{x : 1} 如果没有数据库和集合,那么会默认创建集合和数据库,并插入文档到集合中

MongoDB中的所有写操作都是单个文档级别的原子操作。 有关MongoDB和原子性的更多信息,请参见原子性

3.2、新增操作

db.inventory.insertOne(
{ item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
) //插入文档到集合inventory中,如果集合不存在,那么会默认创建集合

db.inventory.insertMany([
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]); //插入多条文档

3.3、查询操作

db.inventory.find( {} ) // SELECT * FROM inventory

db.inventory.find( { status: "D" } ) // SELECT * FROM inventory WHERE status = "D"

db.inventory.find( { status: { $in: [ "A", "D" ] } } ) // SELECT * FROM inventory WHERE status in ("A", "D")

db.inventory.find( { status: "A", qty: { $lt: 30 } } ) // SELECT * FROM inventory WHERE status = "A" AND qty < 30

db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } ) // SELECT * FROM inventory WHERE status = "A" OR qty < 30

db.inventory.find( {
status: "A",
$or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
} ) // SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")

3.4、删除操作

db.inventory.deleteMany({}) // 从inventory收集中删除所有文档

db.inventory.deleteMany({ status : "A" }) // 从状态字段等于“ A”的inventory集合中删除所有文档

db.inventory.deleteOne( { status: "D" } ) // 删除状态为“ D”的第一个文档

即使从集合中删除所有文档,删除操作也不会删除索引。

3.5、修改操作

先使用插入多条数据插入示例数据,在示例数据的基础上进行更新操作

db.inventory.insertMany( [
{ item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status: "A" },
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
{ item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" }, status: "P" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
{ item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" }, status: "A" }
] ); //插入多条示例文档

db.inventory.updateOne(
{ item: "paper" },
{
$set: { "size.uom": "cm", status: "P" },
$currentDate: { lastModified: true }
}
)
// 使用$set 运算符将size.uom字段的值更新为“ cm”,将状态字段的值更新为“ P”,使用$currentDate运算符将lastModified字段的值更新为当前日期。 如果lastModified字段不存在,则$currentDate将创建该字段

要替换_id字段以外的文档的全部内容,请将一个全新的文档作为第二个参数传递给db.collection.replaceOne()。

在替换文档中,由于_id字段是不可变的,因此可以省略_id字段。如果确实包含_id字段,则它必须与当前值具有相同的值

db.inventory.replaceOne(
{ item: "paper" },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
)//替换了inventory集合中的第一个文件,其中项为"paper":


文档设置后,您将无法更新_id字段的值,也无法将现有文档替换为具有不同_id字段值的替换文档


除以下情况外,MongoDB会在执行写操作后保留文档字段的顺序:

  • _id字段始终是文档中的第一个字段。
  • 包含字段名称renaming 的更新可能导致文档中字段的重新排序

如果updateOne(), updateMany(), or replaceOne() 包含upsert:true,并且没有文档与指定的过滤器匹配,则该操作将创建一个新文档并将其插入。 如果存在匹配的文档,则该操作将修改或替换一个或多个匹配的文档。


4、mongodb java api


Spring Data的MongoRepository和MongoTemplate。


4.1、MongoRepository依次实现了PagingAndSortingRepository、CrudRepository、Spring Data的Repository

  • Repository: 仅仅是一个标识,表明任何继承它的均为仓库接口类
  • CrudRepository: 继承 Repository,实现了一组 CRUD 相关的方法
  • PagingAndSortingRepository: 继承 CrudRepository,实现了一组分页排序相关的方法
  • MongoRepository: 继承 PagingAndSortingRepository,实现一组 mongodb规范相关的方法 //自定义的 XxxxRepository 需要继承 MongoRepository,这样的 XxxxRepository 接口就具备了通用的数据访问控制层的能力(CURD的操作功能)

MongoRepository的缺点是不够灵活,MongoTemplate正好可以弥补不足


4.2、MongoTemplate采用了模板方法设计模式,封装了代码调用获取链接执行语句等操作。

  • MongoTemplate实现了interface MongoOperations。
  • MongoDB documents和domain classes之间的映射关系是通过实现了MongoConverter这个interface的类来实现的。
  • MongoTemplate提供了非常多的操作MongoDB的方法。 它是线程安全的,可以在多线程的情况下使用。
  • MongoTemplate实现了MongoOperations接口, 此接口定义了众多的操作方法如"find", "findAndModify", "findOne", "insert", "remove", "save", "update" and "updateMulti"等。
  • MongoTemplate转换domain object为DBObject,缺省转换类为MongoMappingConverter,并提供了Query, Criteria, and Update等流式API

MongoTemplate的类结构如下:其中有两个重要的操作类


MongoTemplate类结构


MongoTemplate类结构

  • Criteria类:封装所有的语句,以方法的形式查询。
    Criteria类结构

  • Query类:将语句进行封装或者添加排序之类的操作。
    Query类结构

从上面类结构可以知道使用 Query 构造方法,传入一个Criteria类,可以构建一个简单的过滤器去进行CRUD。
下面介绍使用MongoTemplate进行简单的crud

//yml配置
spring:
  data:
    mongodb:
      uri: mongodb://localhost:27017/mytest
//测试代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class MongodbUtil {


    @Autowired
    private MongoTemplate mongoTemplate;
//
//    @Autowired
//    private PersonRepository personRepository;


    /**
     * insert document
     *
     * {
     *     "name" : "cgg",
     *     "info": {
     *         "age" : 18
     *     }
     * }
     */
    @Test
    public void testInsert() {
        Map<String, Object> data = Maps.newHashMap();
        Map<String, Object> info = Maps.newHashMap();
        data.put("name", "cgg");
        info.put("age" , 18);
        data.put("info", info);
        mongoTemplate.insert(data, "inventory");
        System.out.println(mongoTemplate.findAll(Map.class, "inventory"));
    }

    /**
     * select * from inventory where status in ('A')
     */
    @Test
    public void testQuery() {
        Query query = new Query();
        query.addCriteria(Criteria.where("status").in("A"));
        mongoTemplate.executeQuery(query, "inventory", System.out::println);
    }


    /**
     * update inventory set qty = 55 where status in ('A')
     */
    @Test
    public void testUpdate() {
        Query query = new Query();
        query.addCriteria(Criteria.where("status").in("A"));
        Update update = new Update();
        update.set("qty", 55);
        mongoTemplate.updateMulti(query, update, "inventory");
        System.out.println(mongoTemplate.findAll(Map.class, "inventory"));
    }

    /**
     * delete from inventory  where name = 'cgg'
     */
    @Test
    public void testDelete() {
        Query query = new Query();
        query.addCriteria(Criteria.where("name").in("cgg"));
        mongoTemplate.remove(query, "inventory");
        testQuery();
    }

}

5、mongodb客户端

客户端介绍

mongodb客户端有很多,这里推荐大家使用Robo,支持查看各种语言的查询语句、结果集转换,筛选查询,查看查询计划等等
Robo客户端

Robo下载地址Robo studio


6、mongodb对接多数据源

Springboot项目整合mongodb多数据源配置

#yml配置
spring:
  data:
    mongodb:
      one:
        uri: mongodb://localhost:27017/mytest
      two:
        uri: mongodb://localhost:27018/mytest

/**
 * mongodb 多数据源属性配置类
 *
 * @author cgg
 * @since 2021/07/21
 * @version 1.0
 */
@Configuration
public class MongoConfiguration {

    @Bean(name = "oneMongoProperties")
    @Primary
    @ConfigurationProperties(prefix = "spring.data.mongodb.one")
    public MongoProperties masterMongoProperties() {
        return new MongoProperties();
    }

    @Bean(name = "twoMongoProperties")
    @ConfigurationProperties(prefix = "spring.data.mongodb.two")
    public MongoProperties twoMongoProperties() {
        return new MongoProperties();
    }


}

/**
 * mongodb://localhost:27017/mytest 数据源配置类 完成MongoTemplate的注入
 *
 * @author cgg
 * @since 2021/07/21
 * @version 1.0
 */
@Configuration
@EnableMongoRepositories(mongoTemplateRef = "oneMongo")
public class OneMongoTemplateConf {

    private final MongoProperties mongoProperties;

    public OneMongoTemplateConf(@Qualifier("oneMongoProperties") MongoProperties mongoProperties) {
        this.mongoProperties = mongoProperties;
    }

    @Bean(name = "oneMongo")
    @Primary
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(mongoDatabaseFactory(mongoProperties));
    }

    @Bean(name = "oneMongoFactory")
    @Primary
    public MongoDatabaseFactory mongoDatabaseFactory(MongoProperties mongoProperties) {
        return new SimpleMongoClientDatabaseFactory(mongoProperties.getUri());
    }


}


/**
 *
 * mongodb://localhost:27018/mytest 数据源配置类 完成MongoTemplate的注入
 *
 * @author cgg
 * @since 2021/07/21
 * @version 1.0
 */
@Configuration
@EnableMongoRepositories(mongoTemplateRef = "twoMongo")
public class TwoMongoTemplateConf {

    private final MongoProperties mongoProperties;

    public TwoMongoTemplateConf(@Qualifier("twoMongoProperties") MongoProperties mongoProperties) {
        this.mongoProperties = mongoProperties;
    }

    @Bean(name = "twoMongo")
    public MongoTemplate mongoTemplate() {
        return new MongoTemplate(mongoDatabaseFactory(mongoProperties));
    }

    @Bean(name = "twoMongoFactory")
    public MongoDatabaseFactory mongoDatabaseFactory(MongoProperties mongoProperties) {
        return new SimpleMongoClientDatabaseFactory(mongoProperties.getUri());
    }


}

/**
 * mongodb 多数据源测试
 *
 * @author cgg
 * @since 2021/07/21
 * @version 1.0
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class MongoTest {

    @Autowired
    @Qualifier("oneMongo")
    private MongoTemplate oneMongoTemplate;


    @Autowired
    @Qualifier("twoMongo")
    private MongoTemplate twoMongoTemplate;


    /**
     * 向 localhost:27017/mytest插入数据
     */
    @Test
    public void testOneMongoInsert() {
        Map<String, Object> data = Maps.newHashMap();
        Map<String, Object> info = Maps.newHashMap();
        data.put("name", "cgg");
        data.put("attr", "one");
        info.put("age" , 18);
        data.put("info", info);
        oneMongoTemplate.insert(data, "inventory_27017");
        System.out.println(oneMongoTemplate.findAll(Map.class, "inventory_27017"));
    }

    /**
     * 向 localhost:27018/mytest插入数据
     */
    @Test
    public void testTwoMongoInsert() {
        Map<String, Object> data = Maps.newHashMap();
        Map<String, Object> info = Maps.newHashMap();
        data.put("name", "cgg");
        data.put("attr", "two");
        info.put("age" , 18);
        data.put("info", info);
        twoMongoTemplate.insert(data, "inventory_27018");
        System.out.println(twoMongoTemplate.findAll(Map.class, "inventory_27018"));
    }

}

多数据源配置,测试结果展示

多数据源操作结果


7、MongoDB 高级



上面介绍了mongodb的入门使用,关于mongodb,还有数据模型、事务、索引、聚合、安全、复制、分片、管理、存储等等。下一篇将着重介绍Mongodb的更多使用和特性。


posted @ 2021-07-21 09:23  coffeebabe  阅读(1160)  评论(2编辑  收藏  举报