Mongo基础
一、MongoDB中的基本概念和原理
1、MongoDB介绍及概念
MongoDB是一个基于【分布式文件存储】的数据库,它属于NoSql数据库,由C++编写
NoSql可以分为键值型(K-V)和文档型(Document)两类,其中MongoDB就属于文档型NoSql,他文档中是以类似Json的Bson格式进行存储。
同时MongoDB还是一个介于非关系型数据库和关系型数据库之间的产品,是非关系型数据库中功能最丰富,最想关系型数据库的,它支持的数据结构非常松散,是类似Json的Bson,因此可以存储比较复杂的数据类型。
MongoDB最大的特点就是它支持的查询语言非常强大,其语法优点类似于面向对象的查询语言,几乎可以实现类似关系型数据库单表查询的绝大部分功能,而且还支持对数据库建立索引。
对于MongoDB中的概念,结合MySql进行对比
MySql术语 | MongoDB术语 | 解释说明 |
database | database | 数据库 |
table | collection | 表/集合 |
row | document | 行/文档 |
column | field | 列/域 |
index | index | 索引 |
table joins | 表连接/MongoDB不支持 | |
primary key | primary key | 主键(MongoDB自动将_id字段设置为主键) |
(1)数据库database
一个MongoDB中可以建立多个数据库;MongoDB的默认数据库为“db”,该数据库存储在data目录中;MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
有一些数据库名是保留的,可以直接访问这些特殊作用的数据库。
admin:从权限角度来看,这是一个root级别的数据库,要是将一个用户添加到这个数据库,这个用户自动继承所有的数据库权限,一些特定的服务端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器
local:这个数据库永远不会被复制,可以用来存储仅限于本地单台服务器的任意集合
config:当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息
(2)集合Collection
集合就是MongoDB中的文档组,类似于关系型数据库的表,集合没有特定的结构,这意味着我们可以插入不同格式和不同类型的数据,但通常情况下,我们插入集合的数据都会有一定的关联性。
集合的命名规则:
集合中不能有空字符串;
集合不能含有\0,\0结表示集合名称的结尾;
集合不能以“system.”开头,这是为系统集合保留的前缀;
用户创建集合名字不能含有保留字符,有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的结合中包含了该字符串,除非要访问这种系统创建的集合,否则千万不要在名字里出现$。
capped collections
capped collections就是固定大小的collection,他有很高的性能以及队列过期的特性(过期按照插入的顺序),Capped collection是高性能的自动维护对象的插入顺序,它非常适合类似记录日志的功能,和标准的collection不同,我们必须显式的创建一个capped collection,并且指定其大小,单位是字节。collection的数据存储空间是提前分配的。
capped collections可以按照文档的插入顺序保存到集合中,而且这些文档在磁盘上存放的文职也是按照插入顺序来保存的,所以当我们更新capped collections中的文档时,更新后的文档不可以超过更新前的文档大小,这样的话就可以确保所有文档在磁盘上的位置一直保持不变。
由于capped collection是按照文档的插入顺序而不是使用索引来确定插入位置,这样的话可以提高添加数据的效率,MongoDB的操作日志文件oplog.rs就是利用Capped collections来实现的。
在capped collections中,我们可以添加新的对象,也可以更新对象,由于其空间是提前分配的,所以无论是新增还是更新,都不会增加存储空间,如果更新后空间需要增加,则更新会失败;
使用capped collections不能删除一个文档,但是可以使用drop()方法删除collections所有的行,删除之后,我们必须显式的重新创建这个collection。
(3)文档Document
文档是一组键值对(Bson),MongoDB不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是MongoDB很大的特点。
需要注意的是,文档的键值对是有序的;文档中的值不仅可以是在双引号中的字符串,同时还可以是其他集中数据类型(甚至可以是整个嵌入的文档);MongoDB区分数据类型和大小写;和关系型数据库一样,MongoDB不能有重复的键;除了极少数情况,键可以是任意的UTF-8字符。
文档中键的命名规范:键不能含有'\0',这个字符串是用来表示键的结尾; 点和美元符号(.和$)有特别的含义,只有在特定环境下才能使用;以下划线('_')开头的键是保留的,但是不严格要求。
(4)元数据
数据库的信息是存储在集合中,他们使用了系统的命名空间(以dbname.system开头)。
在MongoDB数据库中名字空间 .syatem.* 是包含多种系统信息的特殊集合,例如:
集合命名空间 | 描述 |
dbname.system.namespaces | 列出所有名字空间 |
dbname.system.indexs | 列出所有索引 |
dbname.system.profile | 包含数据库概要信息 |
dbname.system.users | 列出所有可以访问数据库的用户 |
dbname.system.sources | 包含赋值对端(slave)的服务器信息和状态 |
对于修改系统集合中的对象有如下限制:
在system.indexs中插入数据,可以创建索引,但除此之外,表信息是不可变的。
system.users是可修改的,system.profile是可删除的。
2、MongoDB数据类型
下表为MongoDB中常用的几种数据类型
数据类型 | 说明 | 解释 | 举例 |
String | 字符串 | UTR-8编码的字符串才是合法的 | {"name":"lcl"} |
Integer | 整型数值 |
{"age":18} |
|
Boolean | 布尔类型 | {"man":true} | |
Double | 双精度浮点类型 | {"v":13.14} | |
Array | 数组 | {"arr":["lcl","qmm"]} | |
Timestamp | 时间戳 | ||
ObjectID | 对象ID | 用于创建文档的ID | {"_id":ObjectId("123")} |
Null | 空值 | {"v":null} | |
Date | 日期 | {"v":new Date()} | |
Regular | 正则表达式 | 文档中可以包含正则表达式,遵循JS语法 | {"v":/demo/query} |
Code | 代码 | 可以包含js代码 | {"v":function()} |
File | 文件 | 二进制转码(Base64)后存储(文件<16M);GridFS(文件>16M) | GridFS用两个集合来存储一个文件:fs.files与fs.chunks |
这里特殊说明以下ObjectID,其类似于唯一主键,可以快速的生成和排序,包含12bytes,其中前4个字节表示时间戳,接下来的3个字节是机器的识别码,再接着的两个字节是由进程id组成的PID,最后三个字节是随机数。
MongoDB中存储的文档必须有一个_id键,这个键的值可以是任何类型的,默认是个ObjectId对象,同时由于ObjectId中保存了创建的时间戳,所以不需要为文档保存时间戳字段,可以直接使用getTimestamp函数来获取文档的创建时间。
3、图解MongoDB底层原理
MongoDB的部署方案有单机部署、主从部署、副本集(主备)部署、分片部署、副本集与分片混合部署这几种部署方案。
(1)副本集集群:
对于副本集集群,又有主从两种角色,写数据只能通过主节点,然后通过异步的方式将数据同步到从节点;查询则可以从主从里面的任意节点进行查询。
(2)副本集与分片混合部署:
MongDB的集群部署方案有三种角色:实际数据存储节点、配置文件存储节点、路由接入节点
实际数据存储节点:作用就是存储数据
配置文件存储节点:作用存储的是分片键与chunk的关系以及chunk与server的关系
路由接入节点:作用就是在分片的情况下起到负载均衡的作用
MongoDB的客户端直接与路由节点连接,然后从配置节点上查询数据,根据查询结果到实际的数据存储节点上查询和存储数据。
相同的副本集中的节点存储的数据是相同的,副本集中的节点分为主节点、从节点和仲裁节点(非必须),类似于redis的主从+哨兵模式。这样是为了解决高性能、高可用、数据备份
不同的副本集中存储的数据不同,这种设计是为了高扩展。
4、MongoDB的应用场景和不适用场景
(1)适用场景
更高的写入负载:MongoDB更侧重大数据量的写入性能,所以MongoDB非常适合存储“低价值”的数据。
高可用性:MongoDB的主从配置非常简单,并且MongoDB可以快速的处理单点故障,自动、安全的完成故障转移。
数据量很大或者未来会很大,或者表结构不明确:如果使用Mysql这类的关系型数据库,数据扩展是比较困难的,特别是当数据量大的时候去变更数据结构,非常的困难;在Mysql中,当一个单表数据量达到1000W或者达到5-10G的时候,会出现明显的性能下降,此时就需要进行分库分表等操作来进行垂直和水平扩展,并且这些扩展是需要借助驱动层或代理层来完成这类的需求,但是MongoDB内建了多种数据分片的特性,可以很好的适应大数据量的需求。
基于位置的数据查询:MongoDB支持二维空间索引,因此可以快速精确的从指定位置获取数据。
(2)不适用场景
在某些场景下,MongoDB作为一个非关系型数据库有其局限性,MongoDB不支持事务操作,所以需要用到事务的地方不建议使用MongoDB,另外MongoDB不支持join操作,需要复杂查询的应用也不建议使用MongoDB。
二、MongoDB的安装
1、安装与启动
(1)下载&解压&重命名
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.6.11.tgz tar -zxvf mongodb-linux-x86_64-rhel70-3.6.11.tgz mv mongodb-linux-x86_64-rhel70-3.6.11 mongo-3.6.11
(2)配置环境变量
vim /etc/profile
source /etc/profile
profile文件新增mongo配置
export PATH=$JAVA_HOME/bin:/root/rj/mongo/standalone/mongo-3.6.11/bin:$PATH
(3)创建mongo配置文件
mkdir data logs etc
vim etc/mongodb.cfg
mongodb.cfg文件内容
#数据库文件位置 dbpath=/root/rj/mongo/standalone/mongo-3.6.11/data #日志文件位置 logpath=/root/rj/mongo/standalone/mongo-3.6.11/logs/mongodb.log #以追加方式写入日志 logappend=true #是否以守护进程方式运行 fork=true #绑定客户端访问的ip 0.0.0.0 不绑定ip bind_ip=0.0.0.0 #端口 port=27017
(4)启动
./bin/mongod --config etc/mongodb.cfg
2、连接客户端与常用客户端
客户端连接:
./bin/mongo
常用的客户端:
Navicat for mongodb
MongoVUE
Studio 3T
Robo 3T
RockMongo
三、常用命令
1、数据库相关命令
创建数据库:use dbName
> use lcldb
switched to db lcldb
查询所有数据库:show dbs
可以发现下面的命令结果并没有刚才创建的数据库,因为数据库中需要有值才会显示数据库
> show dbs admin 0.000GB config 0.000GB local 0.000GB
插入数据:db.collectionName.insert()
可以看到,插入数据后,重新查看数据库,就有该数据库
> db.lclconllection.insert({"name":"lcl","age":18}) WriteResult({ "nInserted" : 1 }) > show dbs admin 0.000GB config 0.000GB lcldb 0.000GB local 0.000GB
删除数据库:db.dropDatabase()
> db.dropDatabase() { "dropped" : "lcldb", "ok" : 1 } > show dbs admin 0.000GB config 0.000GB local 0.000GB
2、集合相关命令
创建集合:db.createCollection(name,options)
name是集合的名称,options可选参数,指定有关内存大小及索引的选项
options可以是以下参数:
字段 | 类型 | 描述 |
capped | boolean | (可选)如果为true,则创建固定大小的集合,当达到最大值时,将会覆盖最早的文档,当该值为true时,必须指定size大小 |
autoIndex | boolean | (可选)如果为true,自动在_id字段创建索引,默认为false |
size | int | (可选)为固定集合制定一个最大值(以字节计),如果capped为true,也需要指定该字段 |
max | int | (可选)指定固定集合中包含文档的最大数量 |
在插入文档时,MongoDB首先检查固定集合的size字段,然后检查max字段。
> db.createCollection("lcltest") { "ok" : 1 } > show collections lcltest
删除集合:db.collectionName.drop()
> db.lcltest.drop() true > show collections
3、文档相关命令
插入文档:db.collectionName.insert(document)
> db.test.insert({"name":"lcl","age":18}) WriteResult({ "nInserted" : 1 }) > db.test.insert({"name":"qmm","age":18}) WriteResult({ "nInserted" : 1 })
查询文档:db.collection.find(query,projection)
query:(可选)使用查询操作符指定查询条件
projection:(可选)是用投影操作符指定返回的键,查询时返回文档中所有的键值,只需省略该参数即可(默认省略)
如果需要以易懂的方式来读取数据,可以使用pretty()方法,语法:db.collection.find().pretty()
> db.test.find() { "_id" : ObjectId("601c0e692f8c31e7c01fdd2e"), "name" : "lcl", "age" : 18 } { "_id" : ObjectId("601c0e9b2f8c31e7c01fdd2f"), "name" : "qmm", "age" : 18 } { "_id" : ObjectId("601c10142f8c31e7c01fdd30"), "name" : "lcl", "age" : 22 } { "_id" : ObjectId("601c10172f8c31e7c01fdd31"), "name" : "lcl", "age" : 33 }
删除文档:db.collection.remove(<query>,<justOne>)
如果是2.6之后的版本,语法:db.collection.remove(<query>,{justOne:boolean,writeConcern:<document>})
query:(可选)删除文档的条件
justOne:(可选)如果设置为true或1,则只删除一个文档,如果不设置该参数,或使用默认值false,则删除所有匹配条件的文档。
writeConcern:(可选)抛出异常级别
> db.test.remove({"name":"lcl"}) WriteResult({ "nRemoved" : 3 }) > db.test.find() { "_id" : ObjectId("601c0e9b2f8c31e7c01fdd2f"), "name" : "qmm", "age" : 18 }
> db.test.remove({'name':'lcl'},1) WriteResult({ "nRemoved" : 1 }) > db.test.find() { "_id" : ObjectId("601c0e9b2f8c31e7c01fdd2f"), "name" : "qmm", "age" : 18 } { "_id" : ObjectId("601c11022f8c31e7c01fdd33"), "name" : "lcl", "age" : 33 }
limit与skip:limit是限定查询条数,skip是跳过指定的数据
> db.createCollection('lcltest') { "ok" : 1 } > db.lcltest.insert({"title":"test","id":1}) WriteResult({ "nInserted" : 1 }) > db.lcltest.insert({"title":"test","id":2}) WriteResult({ "nInserted" : 1 }) > db.lcltest.insert({"title":"test","id":3}) WriteResult({ "nInserted" : 1 }) > db.lcltest.insert({"title":"test","id":4}) WriteResult({ "nInserted" : 1 }) > db.lcltest.insert({"title":"test","id":5}) WriteResult({ "nInserted" : 1 }) > db.lcltest.insert({"title":"test","id":6}) WriteResult({ "nInserted" : 1 }) > db.lcltest.find().limit(3) { "_id" : ObjectId("601c1a2c2f8c31e7c01fdd34"), "title" : "test", "id" : 1 } { "_id" : ObjectId("601c1a2f2f8c31e7c01fdd35"), "title" : "test", "id" : 2 } { "_id" : ObjectId("601c1a312f8c31e7c01fdd36"), "title" : "test", "id" : 3 } > db.lcltest.find().skip(3) { "_id" : ObjectId("601c1a332f8c31e7c01fdd37"), "title" : "test", "id" : 4 } { "_id" : ObjectId("601c1a362f8c31e7c01fdd38"), "title" : "test", "id" : 5 } { "_id" : ObjectId("601c1a382f8c31e7c01fdd39"), "title" : "test", "id" : 6 }
文档排序:db.collectionName.find().sort(keys,options)
在MongoDB中使用sort()对文档进行排序,在该方法中可以指定排序的字段,并可以使用1或者-1表示升序或者降序,其中1表示升序,-1表示降序。
> db.lcltest1.find().sort({"name":1}) { "_id" : ObjectId("601c1b53203f9cdfbf50b273"), "title" : "test", "name" : 16, "id" : 8 } { "_id" : ObjectId("601c1b45203f9cdfbf50b271"), "title" : "test", "name" : 18, "id" : 5 } { "_id" : ObjectId("601c1b4c203f9cdfbf50b272"), "title" : "test", "name" : 25, "id" : 3 }
4、索引相关命令
MongoDB索引:db.collectionName.createIndex(keys,options)
key为创建索引的字段,options为1表示按照升序创建索引,为-1表示按照降序创建索引,同时也可以设置多个字段索引。
> db.lcltest1.createIndex("name") { "ok" : 0, "errmsg" : "The field 'key' must be an object, but got string", "code" : 14, "codeName" : "TypeMismatch" } > db.lcltest1.createIndex({"title":1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 } > db.lcltest1.createIndex({"title":1,"id":-1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 2, "numIndexesAfter" : 3, "ok" : 1 }
对于createIndex()方法的可选接收参数,列表如下:
可选参数 | 类型 | 描述 |
background | boolean | 创建索引过程中会阻塞其他数据库操作,background可指定以后后台方式创建索引,即增加background可选参数,默认为false |
unique | boolean | 是否为唯一索引,默认为false |
name | String | 索引名称,如果未指定,MongoDB会通过连接索引的字段名和排序顺序胜场一个索引名称 |
dropDups | boolean | 3.0之后版本已废弃,在建立唯一索引时是否删除重复的记录,指定true创建唯一索引,默认为false |
sparse | boolean | 对文档中不存在的字段数据是否启用索引,这个参数要特别注意,如果设置为true的话,在索引字段中不会查出不包括该字段的文档,默认为false |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成TTL设定,设定集合的生存时间 |
v | index version | 索引版本号,默认的索引版本取决于mongodb创建索引时运行的版本 |
weights | document | 索引权重值,数值在1-99999之间,表示该索引相对于其他索引字段的权重得分 |
default_language | string | 对于文本索引,该参数决定了停用词以及词干和词器的规则列表,默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为language |
> db.lcltest1.createIndex({"title":1,"id":-1,"name":1},{background:true}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 3, "numIndexesAfter" : 4, "ok" : 1 }
查询集合索引:db.collectionName.getIndexes()
> db.lcltest1.getIndexes() [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "lcldb.lcltest1" }, { "v" : 2, "key" : { "title" : 1 }, "name" : "title_1", "ns" : "lcldb.lcltest1" }, { "v" : 2, "key" : { "title" : 1, "id" : -1 }, "name" : "title_1_id_-1", "ns" : "lcldb.lcltest1" }, { "v" : 2, "key" : { "title" : 1, "id" : -1, "name" : 1 }, "name" : "title_1_id_-1_name_1", "ns" : "lcldb.lcltest1", "background" : true } ]
查看集合索引大小:db.collectionName.totalIndexSize()
> db.lcltest1.totalIndexSize() 65536
删除指定索引:db.collectionName.dropIndex(indexName)
> db.lcltest1.dropIndex("title_1") { "nIndexesWas" : 4, "ok" : 1 }
删除所有索引:db.collectionName.dropIndexes()
> db.lcltest1.dropIndexes() { "nIndexesWas" : 3, "msg" : "non-_id indexes dropped for collection", "ok" : 1 }
5、聚合查询相关命令
数据准备:
> db.lcltest2.find() { "_id" : ObjectId("601c258a59d44de38d3b4385"), "city" : "BJ", "name" : "kcl1", "age" : 15 } { "_id" : ObjectId("601c259259d44de38d3b4386"), "city" : "BJ", "name" : "kcl2", "age" : 17 } { "_id" : ObjectId("601c259459d44de38d3b4387"), "city" : "BJ", "name" : "kcl2", "age" : 19 } { "_id" : ObjectId("601c25a059d44de38d3b4388"), "city" : "BJ", "name" : "kcl4", "age" : 34 } { "_id" : ObjectId("601c25a359d44de38d3b4389"), "city" : "BJ", "name" : "kcl5", "age" : 34 } { "_id" : ObjectId("601c25b559d44de38d3b438a"), "city" : "SH", "name" : "lcl1", "age" : 31 } { "_id" : ObjectId("601c25bc59d44de38d3b438b"), "city" : "SH", "name" : "lcl2", "age" : 23 } { "_id" : ObjectId("601c25c259d44de38d3b438c"), "city" : "SH", "name" : "lcl3", "age" : 18 }
group聚合:db.collections.aggregate([{$group:{_id:$oldField,newField2:{function:oldField2}}])
解释以下上面的表达式,db.collections.aggregate([{$group: {_id 这些是固定的,表示要使用聚合查询相关的命令,其中_id是必须写,并且值表示使用哪个字段进行聚合,newField表示聚合查询后得到的列,而oldField表示原collection中的列,需要使用$进行获取对应的值。
下面的所有命令都是按照上面的表达式进行处理的。
$sum求和:
> db.lcltest2.aggregate([{$group:{_id:"$city",sum123:{$sum:"$age"}}}]) { "_id" : "SH", "sum123" : 72 } { "_id" : "BJ", "sum123" : 119 }
$avg求平均值:
> db.lcltest2.aggregate([{$group:{_id:"$city",sum123:{$avg:"$age"}}}]) { "_id" : "SH", "sum123" : 24 } { "_id" : "BJ", "sum123" : 23.8 }
$min求最小值
> db.lcltest2.aggregate([{$group:{_id:"$city",sum123:{$min:"$age"}}}]) { "_id" : "SH", "sum123" : 18 } { "_id" : "BJ", "sum123" : 15 }
$max求最大值
> db.lcltest2.aggregate([{$group:{_id:"$city",sum123:{$max:"$age"}}}]) { "_id" : "SH", "sum123" : 31 } { "_id" : "BJ", "sum123" : 34 }
$match取值后分组
例如获取每个城市年龄在19-40之间的人数
> db.lcltest2.aggregate([{$match:{age:{$gt:19,$lte:40}}},{$group:{_id:"$city",count123:{$sum:1}}}]) { "_id" : "SH", "count123" : 2 } { "_id" : "BJ", "count123" : 2 }
$sort按照指定列排序
> db.lcltest2.aggregate([{$sort:{age:-1}}]) { "_id" : ObjectId("601c25a059d44de38d3b4388"), "city" : "BJ", "name" : "kcl4", "age" : 34 } { "_id" : ObjectId("601c25a359d44de38d3b4389"), "city" : "BJ", "name" : "kcl5", "age" : 34 } { "_id" : ObjectId("601c25b559d44de38d3b438a"), "city" : "SH", "name" : "lcl1", "age" : 31 } { "_id" : ObjectId("601c25bc59d44de38d3b438b"), "city" : "SH", "name" : "lcl2", "age" : 23 } { "_id" : ObjectId("601c259459d44de38d3b4387"), "city" : "BJ", "name" : "kcl2", "age" : 19 } { "_id" : ObjectId("601c25c259d44de38d3b438c"), "city" : "SH", "name" : "lcl3", "age" : 18 } { "_id" : ObjectId("601c259259d44de38d3b4386"), "city" : "BJ", "name" : "kcl2", "age" : 17 } { "_id" : ObjectId("601c258a59d44de38d3b4385"), "city" : "BJ", "name" : "kcl1", "age" : 15 }
$limit获取前指定条数数据
> db.lcltest2.aggregate([{$limit:3}]) { "_id" : ObjectId("601c258a59d44de38d3b4385"), "city" : "BJ", "name" : "kcl1", "age" : 15 } { "_id" : ObjectId("601c259259d44de38d3b4386"), "city" : "BJ", "name" : "kcl2", "age" : 17 } { "_id" : ObjectId("601c259459d44de38d3b4387"), "city" : "BJ", "name" : "kcl2", "age" : 19 }
$project设置显示或不显示哪些字段,显示用1表示,不显示用0表示
> db.lcltest2.aggregate([{$project:{_id:0,city:1,name:1}}]) { "city" : "BJ", "name" : "kcl1" } { "city" : "BJ", "name" : "kcl2" } { "city" : "BJ", "name" : "kcl2" } { "city" : "BJ", "name" : "kcl4" } { "city" : "BJ", "name" : "kcl5" } { "city" : "SH", "name" : "lcl1" } { "city" : "SH", "name" : "lcl2" } { "city" : "SH", "name" : "lcl3" }
$lookup用于多文档关联,类似于sql的多表关联
三、MongoDB的JAVA客户端
1、mongodb-java-api(基本上不使用)
由于现在基本上不用了,直接贴出代码
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.18</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.10.1</version> </dependency> <!-- 单元测试Junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
@SpringBootTest @Slf4j class LclGalaxyMongoApplicationTests { @Test void contextLoads() { } private MongoClient client; @Before public void init(){ client = new MongoClient("127.0.0.1",27017); } @Test public void createConnection(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); mongoDatabase.createCollection("mycollection"); log.info("集合创建成功"); } public void getCollections(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); MongoCollection<Document> mycollection = mongoDatabase.getCollection("mycollection"); log.info("获取集合成功:{}",mycollection.getNamespace()); MongoIterable<String> names = mongoDatabase.listCollectionNames(); for (String name : names){ log.info("循环集合名称:{}",name); } } public void insertDocument(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); MongoCollection<Document> mycollection = mongoDatabase.getCollection("mycollection"); Document document1 = new Document("name","lcl").append("age",18).append("city","bj"); Document document2 = new Document("name","qmm").append("age",16).append("city","ly"); Document document3 = new Document("name","zbx").append("age",27).append("city","zz"); Document document4 = new Document("name","lmj").append("age",31).append("city","jx"); Document document11 = new Document("name","lcl1").append("age",181).append("city","bj1"); Document document21 = new Document("name","qmm1").append("age",161).append("city","ly1"); Document document31 = new Document("name","zbx1").append("age",271).append("city","zz1"); Document document41 = new Document("name","lmj1").append("age",311).append("city","jx1"); Document document12 = new Document("name","lcl2").append("age",182).append("city","bj2"); Document document22 = new Document("name","qmm2").append("age",162).append("city","ly2"); Document document32 = new Document("name","zbx2").append("age",272).append("city","zz2"); Document document42 = new Document("name","lmj2").append("age",312).append("city","jx2"); Document document13 = new Document("name","lcl3").append("age",183).append("city","bj3"); Document document23 = new Document("name","qmm3").append("age",163).append("city","ly3"); Document document33 = new Document("name","zbx3").append("age",273).append("city","zz3"); Document document43 = new Document("name","lmj3").append("age",313).append("city","jx3"); List<Document> documentList = Arrays.asList(document1,document2,document3,document4); mycollection.insertMany(documentList); log.info("插入文档成功"); FindIterable<Document> documents = mycollection.find(); for (Document document : documents){ log.info("插入后的结果:【{}】", document.toJson()); } } public void findDocument(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); MongoCollection<Document> mycollection = mongoDatabase.getCollection("mycollection"); FindIterable<Document> documents = mycollection.find(); for (Document document : documents){ log.info("文档循环结果:【{}】", document.toJson()); } } public void updateDocument(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); MongoCollection<Document> mycollection = mongoDatabase.getCollection("mycollection"); mycollection.updateMany(Filters.eq("name","lcl"), new Document("age",31)); FindIterable<Document> documents = mycollection.find(); for (Document document : documents){ log.info("更新后的结果:【{}】", document.toJson()); } } public void deleteDocument(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); MongoCollection<Document> mycollection = mongoDatabase.getCollection("mycollection"); mycollection.deleteMany(Filters.eq("city","jx")); FindIterable<Document> documents = mycollection.find(); for (Document document : documents){ log.info("删除后的结果:【{}】", document.toJson()); } } public void query(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); MongoCollection<Document> mycollection = mongoDatabase.getCollection("mycollection"); Document first = mycollection.find().first(); log.info("查询第一条的city:{}",first.get("city")); //查询指定字段 Document document = new Document().append("_id",0).append("city",0).append("name",1); FindIterable<Document> projection = mycollection.find().projection(document); for (Document document1 : projection){ log.info("按条件输出结果:【{}】", document1.toJson()); } } public void query1(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); MongoCollection<Document> mycollection = mongoDatabase.getCollection("mycollection"); //查询指定字段 Document document = new Document().append("age",-1); FindIterable<Document> projection = mycollection.find().sort(document); for (Document document1 : projection){ log.info("排序输出结果:【{}】", document1.toJson()); } } public void likequery(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); MongoCollection<Document> mycollection = mongoDatabase.getCollection("mycollection"); Pattern pattern = Pattern.compile("^.*l.*$", Pattern.CASE_INSENSITIVE); BasicDBObject query = new BasicDBObject("name",pattern); FindIterable<Document> projection = mycollection.find(query); for (Document document1 : projection){ log.info("模糊查询输出结果:【{}】", document1.toJson()); } } public void page(){ MongoDatabase mongoDatabase = client.getDatabase("lcltest5"); MongoCollection<Document> mycollection = mongoDatabase.getCollection("mycollection"); Pattern pattern = Pattern.compile("^.*l.*$", Pattern.CASE_INSENSITIVE); BasicDBObject query = new BasicDBObject("name",pattern); Document document = new Document().append("age",-1); FindIterable<Document> projection = mycollection.find(query).sort(document).skip(2).limit(3); for (Document document1 : projection){ log.info("分页查询输出结果:【{}】", document1.toJson()); } } }
2、springboot集成mongodb(MongoTemplate)
可以直接使用上面api中的命令,直接调用mongo客户端提供的api即可,和上面方法中唯一的区别就是这里直接使用了springboot提供的MongoTemplate
spring: data: mongodb: host: 127.0.0.1 port: 27017 database: db6
@Service @Slf4j public class MongDBService { @Autowired private MongoTemplate mongoTemplate; public void createConnection(){ MongoCollection<Document> mycollection = mongoTemplate.createCollection("lcltest5"); log.info("集合创建成功"); } public void getCollections(){ MongoCollection<Document> mycollection = mongoTemplate.getCollection("lcltest5"); log.info("获取集合成功:{}",mycollection.getNamespace()); Set<String> collectionNames = mongoTemplate.getCollectionNames(); for (String name : collectionNames){ log.info("循环集合名称:{}",name); } } public void insertDocument(){ MongoCollection<Document> mycollection = mongoTemplate.getCollection("lcltest5"); Document document1 = new Document("name","lcl").append("age",18).append("city","bj"); Document document2 = new Document("name","qmm").append("age",16).append("city","ly"); Document document3 = new Document("name","zbx").append("age",27).append("city","zz"); Document document4 = new Document("name","lmj").append("age",31).append("city","jx"); Document document11 = new Document("name","lcl1").append("age",181).append("city","bj1"); Document document21 = new Document("name","qmm1").append("age",161).append("city","ly1"); Document document31 = new Document("name","zbx1").append("age",271).append("city","zz1"); Document document41 = new Document("name","lmj1").append("age",311).append("city","jx1"); Document document12 = new Document("name","lcl2").append("age",182).append("city","bj2"); Document document22 = new Document("name","qmm2").append("age",162).append("city","ly2"); Document document32 = new Document("name","zbx2").append("age",272).append("city","zz2"); Document document42 = new Document("name","lmj2").append("age",312).append("city","jx2"); Document document13 = new Document("name","lcl3").append("age",183).append("city","bj3"); Document document23 = new Document("name","qmm3").append("age",163).append("city","ly3"); Document document33 = new Document("name","zbx3").append("age",273).append("city","zz3"); Document document43 = new Document("name","lmj3").append("age",313).append("city","jx3"); List<Document> documentList = Arrays.asList(document1,document2,document3,document4, document11,document21,document31,document41, document12,document22,document32,document42); mycollection.insertMany(documentList); log.info("插入文档成功"); FindIterable<Document> documents = mycollection.find(); for (Document document : documents){ log.info("插入后的结果:【{}】", document.toJson()); } } public void findDocument(){ MongoCollection<Document> mycollection = mongoTemplate.getCollection("lcltest5"); FindIterable<Document> documents = mycollection.find(); for (Document document : documents){ log.info("文档循环结果:【{}】", document.toJson()); } } public void updateDocument(){ MongoCollection<Document> mycollection = mongoTemplate.getCollection("lcltest5"); mycollection.updateMany(Filters.eq("name","lcl"), new Document("$set",new Document("age",31))); FindIterable<Document> documents = mycollection.find(); for (Document document : documents){ log.info("更新后的结果:【{}】", document.toJson()); } } public void deleteDocument(){ MongoCollection<Document> mycollection = mongoTemplate.getCollection("lcltest5"); mycollection.deleteMany(Filters.eq("city","jx")); FindIterable<Document> documents = mycollection.find(); for (Document document : documents){ log.info("删除后的结果:【{}】", document.toJson()); } } public void query(){ MongoCollection<Document> mycollection = mongoTemplate.getCollection("lcltest5"); Document first = mycollection.find().first(); log.info("查询第一条的city:{}",first.get("city")); //查询指定字段 Document document = new Document().append("_id",0).append("city",1).append("name",1); FindIterable<Document> projection = mycollection.find().projection(document); for (Document document1 : projection){ log.info("按条件输出结果:【{}】", document1.toJson()); } } public void query1(){ MongoCollection<Document> mycollection = mongoTemplate.getCollection("lcltest5"); //查询指定字段 Document document = new Document().append("age",-1); FindIterable<Document> projection = mycollection.find().sort(document); for (Document document1 : projection){ log.info("排序输出结果:【{}】", document1.toJson()); } } public void likequery(){ MongoCollection<Document> mycollection = mongoTemplate.getCollection("lcltest5"); Pattern pattern = Pattern.compile("^.*l.*$", Pattern.CASE_INSENSITIVE); BasicDBObject query = new BasicDBObject("name",pattern); FindIterable<Document> projection = mycollection.find(query); for (Document document1 : projection){ log.info("模糊查询输出结果:【{}】", document1.toJson()); } } public void page(){ MongoCollection<Document> mycollection = mongoTemplate.getCollection("lcltest5"); Pattern pattern = Pattern.compile("^.*l.*$", Pattern.CASE_INSENSITIVE); BasicDBObject query = new BasicDBObject("name",pattern); Document document = new Document().append("age",-1); FindIterable<Document> projection = mycollection.find(query).sort(document).skip(2).limit(3); for (Document document1 : projection){ log.info("分页查询输出结果:【{}】", document1.toJson()); } } public void maintest(){ createConnection(); getCollections(); insertDocument(); findDocument(); updateDocument(); deleteDocument(); query(); query(); likequery(); page(); } }
实际开发中,这样用非常不方便
3、springboot集成mongodb(MongoRepository)
@RequiredArgsConstructor @Service @Slf4j public class MongoService2 { private final UserRepository userRepository;
public void insertDocument(){ userRepository.insert(UserDo.builder()._id("1").name("lcl").city("bj").age(18).build()); userRepository.insert(UserDo.builder()._id("2").name("1mm").city("ly").age(15).build()); userRepository.insert(UserDo.builder()._id("3").name("zbx").city("zz").age(22).build()); userRepository.insert(UserDo.builder()._id("4").name("lcl1").city("bj1").age(181).build()); userRepository.insert(UserDo.builder()._id("5").name("1mm1").city("ly1").age(151).build()); userRepository.insert(UserDo.builder()._id("6").name("zbx1").city("zz1").age(221).build()); userRepository.insert(UserDo.builder()._id("7").name("lcl1").city("bj1").age(181).build()); userRepository.insert(UserDo.builder()._id("8").name("1mm1").city("ly1").age(151).build()); userRepository.insert(UserDo.builder()._id("9").name("zbx1").city("zz1").age(221).build()); log.info("插入文档成功"); List<UserDo> userDoList = userRepository.findAll(); for (UserDo userDo : userDoList){ log.info("插入后的结果:【{}】", JSON.toJSONString(userDo)); } } public void findDocument(){ List<UserDo> userDoList = userRepository.findAll(); for (UserDo userDo : userDoList){ log.info("文档循环结果:【{}】", JSON.toJSONString(userDo)); } } public void updateDocument(){ Optional<UserDo> userDoOptional = userRepository.findById("1"); if(userDoOptional.isPresent()){ UserDo userDo = userDoOptional.get(); userDo.setCity("beijing"); UserDo save = userRepository.save(userDo); log.info("更新后的结果:【{}】", JSON.toJSONString(save)); } List<UserDo> userDoList = userRepository.findAll(); for (UserDo userDo : userDoList){ log.info("更新后的结果:【{}】", JSON.toJSONString(userDo)); } } public void deleteDocument(){ ExampleMatcher matcher = ExampleMatcher.matching().withIgnorePaths("_id","name","age","city"); Example<UserDo> userDoExample = Example.of(UserDo.builder().name("lcl1").build(), matcher); Optional<UserDo> userDoOptional = userRepository.findOne(userDoExample); if(userDoOptional.isPresent()){ userRepository.delete(userDoOptional.get()); } List<UserDo> userDoList = userRepository.findAll(); for (UserDo userDo : userDoList){ log.info("删除后的结果:【{}】", JSON.toJSONString(userDo)); } } public void query1(){ Sort.Order order = new Sort.Order(Sort.Direction.ASC, "age"); Sort sort = Sort.by(order); List<UserDo> userDoList = userRepository.findAll(sort); for (UserDo userDo : userDoList){ log.info("排序输出结果:【{}】", JSON.toJSONString(userDo)); } } public void likequery(){ List<UserDo> userDoList = userRepository.findUserByNameLike("l"); for (UserDo userDo : userDoList){ log.info("模糊查询输出结果:【{}】", JSON.toJSONString(userDo)); } } public void page(){ PageRequest pageRequest = PageRequest.of(2,3); Page<UserDo> userDos = userRepository.findAll(pageRequest); List<UserDo> userDoList = userDos.getContent(); for (UserDo userDo : userDoList){ log.info("分页查询输出结果:【{}】", JSON.toJSONString(userDo)); } } }
@Repository public interface UserRepository extends MongoRepository<UserDo, String> { List<UserDo> findUserByNameLike(String STR); }
-----------------------------------------------------------
---------------------------------------------
朦胧的夜 留笔~~