集合
表
6.mongoDB存储原理
mongoDb采用内存加磁盘的方式存储数据;
mongoDb支持数据分片,当单一的服务器中磁盘不够用的时候,还可以串联其他服务器;
客户端的请求到达内存时,先在日志中记录下操作记录,然后再去操作内存;
内存中的日志每10ms向磁盘中的日志进行同步一次,数据则每分钟同步一次;
客户端先去内存中查询数据,内存中没有再去查询磁盘;
当客户端写入的时候,会先写入到内存中,内存中写入后请求直接返回,内存中的数据会根据同步策略同步到磁盘;
如果机器宕机,在重启服务的时候会解析磁盘中的日志和磁盘中的数据进行对比,将未入到磁盘中的数据写入磁盘,但可能会丢失10ms的数据;
7.数据库操作 mongodb默认保留的数据库
admin : 从权限角度考虑, 这是 root 数据库, 如果将一个用户添加到这个数据库, 这个用户自动继承所有数据库的权限, 一些特定的服务器端命令也只能从这个数据库运行, 比如列出所有的数据库或者关闭服务器
local : 数据永远不会被复制, 可以用来存储限于本地的单台服务器的集合 (部署集群, 分片等)
config : Mongo 用于分片设置时, config 数据库在内部使用, 用来保存分片的相关信息
2.1创建并选择数据库
创建并选择数据库的语法格式:
如果数据库不存在则自动创建,例如,以下语句创建 articledb数据库:
注意: 在 MongoDB 中,集合只有在内容插入后才会显示!
2.2查看数据库
查看所有的数据库
show dbs
或
show databases
查看当前正在使用的数据库命令
2.3数据库的删除
8.集合操作 8.1查看集合 查看集合的语法如下:
8.2创建集合 创建集合的语法如下:
db. createCollection( '集合名称' , [ options] )
options可以是如下参数:
字段
类型
描述
capped
布尔
(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。 当该值为 true 时,必须指定 size 参数。
size
数值
(可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。
max
数值
(可选)指定固定集合中包含文档的最大数量。
8.3删除集合 删除集合的语法如下:
9.文档的操作 9.1 文档的插入
单个文档的插入,语法如下:
db.collection.insertOne(
<document or array of documents>,
{
writeConcern: <document>,
ordered: <boolean>
}
)
注意点:
1)**comment集合如果不存在,则会隐式创建 **
2)**mongo中的数字,默认情况下是double类型,如果要存整型,必须使用函数NumberInt(整型数字)。 **
3)插入当前日期使用 new Date()
4)插入的数据没有指定 _id ,会自动生成主键值
5)如果某字段没值,可以赋值为null,或不写该字段。
插入一条数据如下:
/*插入一条数据*/
db.articledb.insertOne( { "name" : "lisi" ,"age" :NumberInt( 20 ) } ) ;
文档的批量插入,语法如下:
db. 集合名称. insertMany(
[ < document 1 > , < document 2 > , . . . ] ,
{
writeConcern: 1 ,
ordered: true
}
)
db. articledb. insertMany( [ {"name" :"wangwu" , "age" :NumberInt( 21 ) }, {"name" :"zhaoliu" , "age" :NumberInt( 23 ) }] )
内嵌文档的插入
db. user . insert ( {"name" :"wangnima" , "age" :NumberInt( 15 ) , "home" :{"province" :"河南省" , "county" :"扶沟县" }})
数组的插入
db. user . insert ( {"name" :"baqi" , "age" :NumberInt( 16 ) , "score" :[ {"chinese" :NumberInt( 99 ) }, {"math" :NumberInt( 109 ) }, {"english" :NumberInt( 425 ) }] })
4.2文档的查询 文档查询的语法格式如下:
db. 集合名称. find( < query> , [ projection] )
query 可选,使用查询操作符指定查询条件
projection 可选,使用投影操作符指定返回的键。查询时返回文档中所有键值,只需省略该参数即可(默认省略)。投影时,id为1的时候,其他字段必须是1;id是0的时候,其他字段可以是0;如果没有_id字段约束,多个其他字段必须同为0或同为1。
如果需要以容读的方式来读取数据,可以使用pretty()方法:
db. 集合名称. find( < query> , [ projection] ) . pretty( ) ;
查询集合的所有文档
db. collection. find( )
或
db. collection. find( {})
==发现每条文档会有一个叫_id的字段,这个相当于我们原来关系数据库中表的主键,当你在插入文档记录时没有指定该字段, MongoDB会自动创建,其类型是ObjectID类型。 如果我们在插入文档记录时指定该字段也可以,其类型可以是ObjectID类型,也可以是MongoDB支持的任意类型。==
添加参数查询文档
查询出所有匹配参数的文档
db. articledb. find( {"age" :"22" })
使用findOne查询出匹配的第一条数据
db. articledb. findOne( {"age" :NumberInt( 22 ) })
查询嵌套文档
db. user . find( {"home.province" :"江苏省" })
db. user . find( {"home" :{"province" :"江苏省" , "county" :"昆山市" , "town" :"陆家镇" }})
db.user.find({“home”:{“province”:”江苏省”,”county”:”昆山市”,”town”:”陆家镇”}})
查询数组
查询兴趣是“reading”,“movie”,“swimming” 的用户的userid及nikename
db. comment . find( {hobby:[ "reading" , "movie" , "swimming" ] }, {userid:1 , nickname:1 })
查询兴趣中有“movie”这一项的用户的userid及nikename:
db. comment . find( {hobby:"movie" }, {userid:1 , nickname:1 })
查询喜欢“reading”和“movie”的用户的userid及nikename:
db. comment . find( {hobby:{$all :[ "reading" , "movie" ] }}, {userid:1 , nickname:1 })
查询喜欢“reading”或“movie”的用户的userid及nikename:
db. comment . find( {hobby:{$in :[ "reading" , "movie" ] }}, {userid:1 , nickname:1 }) .
查询兴趣爱好有三个的用户的userid及nikename:
db. comment . find( {hobby:{$size:3 }}, {userid:1 , nickname:1 })
4.3文档的更新 语法格式:
db. 集合名称. updateOne(
< query> ,
< update > ,
{
upsert: < boolean > ,
multi: < boolean > ,
writeConcern: < document>
}
) ;
query:描述更新的查询条件
update:描述更新的动作及新的内容;
options:描述更新的选项
upsert:可选,如果不存在update的记录,是否插入新的记录。默认false,不插入
multi:可选,是否按条件查询出的多条记录全部更新。默认false,只更新找到的第1 条记录
writeConcern :可选,决定一个写操作落到多少个节点上才算成功。
覆盖修改
当我们未指定其他要修改的字段时,修改的话就会覆盖其他字段的值,其他字段的值为null
局部修改
要使用修改器$set来实现局部修改
db. articledb. update ( {"name" :"zhangsan" }, {$set :{"age" :NumberInt( 22 ) }})
批量修改
mongodb默认只会修改第一条数据,如果要根据字段批量删除字段,需要设置multi为true
db. articledb. update ( {"age" :22 }, {$set :{"name" :"zhangquandan" }}, {"multi" :true })
新增文档字段
db. user . update ( {"name" :"zhangsan" }, {$set :{"address" :"苏州" }})
删除文档字段
db. user . update ( {"name" :"zhangsan" }, {$unset:{"address" :"苏州" }})
修改嵌套文档
修改嵌套数据:
db. user . update ( {"name" :"wangnima" }, {$set :{"home.province" :"江苏省" }})
db. user . update ( {"name" :"wangnima" }, {$set :{"home" :{"province" :"江苏省" , "county" :"昆山市" }}})
向内嵌文档中添加数据:
db. user . update ( {"name" :"wangnima" }, {$set :{"home.town" :"陆家镇" }})
修改数组
mongodb中数组的下标也是从0开始的
数组的修改
db. user . update ( {"name" :"qianba" }, {$set :{"likes.1" :"打豆豆" }})
数组中内嵌文档的修改
db. user . update ( {"name" :"baqi" }, {$set :{"score.0.chinese" :NumberInt( 119 ) }})
4.4文档的删除 删除文档的语法结构:
db. 集合名称. remove( 条件)
or
db. 集合名称. deleteOne( 条件)
以下语句可以将数据全部删除,请慎用
remove 命令需要配合查询条件使用;
匹配查询条件的文档会被删除;
指定一个空文档条件会删除所有文档;
db. articledb. remove( {"name" :"zhaoliu" })
4.5文档的统计查询 统计查询使用count()方法,语法如下:
db. collection. count ( query, options)
or
db. collection. countDocuments( query, options)
统计所有记录数
按条件统计记录数
db. articledb. count ( {"age" :22 })
4.6文档的分页查询 可以使用limit()方法来读取指定数量的数据,使用skip()方法来跳过指定数量的数据。
基本语法如下所示:
db. COLLECTION_NAME. find( ) . limit ( NUMBER) . skip( NUMBER)
如果你想返回指定条数的记录,可以在find方法后调用limit来返回结果(TopN),默认值20,例如:
返回前两条数据
db. articledb. find( ) . limit ( 2 )
skip方法同样接受一个数字参数作为跳过的记录条数。(前N个不要),默认值是0,例如:
查询第3-4条数据
db. articledb. find( ) . limit ( 2 ) . skip( 2 )
4.7文档的排序查询 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和-1来指定排序的方式,**其中 1 为升序排列,而 -1 是用 于降序排列 **。
语法如下所示:
db. COLLECTION_NAME. find( ) . sort( {KEY :1 })
或
db. 集合名称. find( ) . sort( 排序方式)
例如:按照年龄的升序进行排序
db. articledb. find( ) . sort( {"age" :1 })
4.8文档的模糊查询 MongoDB的模糊查询是通过正则表达式的方式实现的。正则表达式是js的语法,直接量的写法。格式为:
db. collection. find( {field:/ 正则表达式/ })
或
db. 集合. find( {字段:/ 正则表达式/ })
db. 集合. find( {字段:/ ^ 正则表达式/ })
db. 集合. find( {字段:/ 正则表达式$/ })
例如:查询name中含有quan的文档
db. articledb. find( {"name" :/ quan/ })
查询以li开头的文档
db. articledb. find( {"name" :/ ^ li/ })
4.9文档的比较查询 <, <=, >, >= 这个操作符是文档的比较查询,格式如下:
db. 集合名称. find( { "field" : { $gt: value }})
db. 集合名称. find( { "field" : { $lt: value }})
db. 集合名称. find( { "field" : { $gte: value }})
db. 集合名称. find( { "field" : { $lte: value }})
db. 集合名称. find( { "field" : { $ne: value }})
例如:查询年龄大于21的文档
db. articledb. find( {"age" :{$gt:NumberInt( 21 ) }})
4.10文档的包含查询 包含使用$in操作符。
不包含使用$nin操作符。
例如:查询年龄在21-22之间的文档
db. articledb. find( {"age" :{$in :[ 21 , 22 ] }})
查询年龄不在21-22之间的文档
db. articledb. find( {"age" :{$nin:[ 21 , 22 ] }})
4.11文档的去重查询 去重的操作语法如下:
如:按照年龄去重
4.12文档的投影查询 如果要查询结果返回部分字段,则需要使用投影查询(不显示所有字段,只显示指定的字段)。而_id 会默认显示。
其中1表示显示,而0表示排除
db. articledb. find( {"name" :"zhangsan" }, {"name" :1 })
如果不想显示_id,可以指定_id为0
db. articledb. find( {"name" :"zhangsan" }, {"name" :1 , "_id" :0 })
4.13条件连接查询
and操作符
我们如果需要查询同时满足两个以上条件,需要使用$and操作符将条件进行关联。(相 当于SQL的and) 格式为:
示例:查询年龄大于20,并且年龄小于等于21的文档
db. articledb. find( {$and :[ {"age" :{$gt:NumberInt( 20 ) }}, {"age" :{$lte:NumberInt( 21 ) }}] })
or操作符
如果两个以上条件之间是或者的关系,我们使用$or操作符进行关联,与前面 and的使用方式相同 格式为:
db. articledb. find( {$or :[ {"age" :{$lt:NumberInt( 21 ) }}, {"name" :"zhangquandan" }] })
and操作符 和**or操作符**联合查询
例如关系型数据库的查询语句:
SELECT . . . FROM user WHERE age >= 18 AND ( name = "zhangsan" OR name = "lisi" )
db. user . find( {"age" :{$gt:18 }, $or :[ {"name" :"zhangsan" }, {"name" :"lisi" }] })
4.14文档数组的查询 新增一个数组数据如下:
db. user . insert ( {"name" :"qianba" , "age" :12 , "likes" :[ "看电影" , "骑行" ] })
按照数组内容查询
查询喜欢看电影的文档信息:
db. user . find( {"likes" :"看电影" })
db. students. updateOne( {"name" : "张力" }, {$set : {"books.1" : "C#" }})
按照数组长度查询
db. user . find( {"likes" :{$size:2 }})
10.$type操作符 $type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。
MongoDB 中可以使用的类型如下表所示:
类型
数字
Double
1
String
2
Object
3
Array
4
Binary data
5
Undefined(已废除)
6
Object id
7
Boolean
8
Date
9
Null
10
Regular Expression
11
JavaScript
13
Symbol
14
JavaScript (with scope)
15
32-bit integer
16
Timestamp
17
64-bit integer
18
Min key
255
Max key
127
如查询age的类型为double类型的文档
db. user . find( {"age" :{$type :1 }})
11.索引 11.1索引的概述 索引支持在MongoDB中高效地执行查询。如果没有索引,MongoDB必须执行全集合扫描,即扫描集合中的每个文档,以选择与查询语句 匹配的文档。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
如果查询存在适当的索引,MongoDB可以使用该索引限制必须检查的文档数。
索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB还可以使用索引中的排序返回排序结果。
官网文档:https://docs.mongodb.com/manual/indexes/
了解: MongoDB索引使用B树数据结构(确切的说是B-Tree,MySQL是B+Tree)
11.2索引的分类 11.2.1单字段索引 MongoDB支持在文档的单个字段上创建用户定义的升序/降序索引,称为单字段索引(Single Field Index)。 对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为MongoDB可以在任何方向上遍历索引。
11.2.2 复合索引 **MongoDB还支持多个字段的用户定义索引,即复合索引(Compound Index) **。 复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由 { userid: 1, score: -1 } 组成,则索引首先按userid正序排序,然后 在每个userid的值内,再在按score倒序排序。
11.2.3 其他索引
地理空间索引(Geospatial Index)
为了支持对地理空间坐标数据的有效查询,MongoDB提供了两种特殊的索引:
返回结果时使用平面几何的二维索引和返回结果时使用球面 几何的二维球面索引。
文本索引(Text Indexes)
MongoDB提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如“the”、“a”、“or”), 而将集合中的词作为词干,只存储根词。
哈希索引(Hashed Indexes)
为了支持基于散列的分片,MongoDB提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支 持相等匹配,不支持基于范围的查询。
11.3索引的创建 创建索引,语法如下:
db. 集合名称. createIndex( keys , options)
db. 集合名称. createIndex( {"title" :1 , "description" :- 1 })
说明: 语法中 Key 值为你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。
options的列表
创建单字段索引
其中-1表示降序
db. articledb. createIndex( {"age" :- 1 })
创建复合索引
db. articledb. createIndex( {"age" :1 , "name" :- 1 })
11.4索引的查看 查看当前集合的所有索引:
mongodb会默认根据主键创建一个主键
MongoDB在创建集合的过程中,在 _id 字段上创建一个唯一的索引,默认名字为 id ,该索引可防止客户端插入两个具有相同值的文 档,您不能在_id字段上删除此索引。 注意:该索引是唯一索引,因此值不能重复,即 _id 值不能重复的。在分片集群中,通常使用 _id 作为片键。
11.5索引的删除 可以移除指定的索引,或移除所有索引
移除指定的索引
语法:
例如:删除age字段上的降序索引
db. articledb. dropIndex( {"age" :- 1 })
删除所有索引
11.6性能分析工具explain
执行计划
分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plan)来查看查询的情况,如查询耗费的时间、是 否基于索引查询等。
通常,我们想知道,建立的索引是否有效,效果如何,都需要通过执行计划查看。
语法:
db. collection. find( query, options) . explain ( options)
例如:
db. articledb. find( {"name" :"zhangquandan" }) . explain ( )
观察结果可知,当前是使用的是集合扫描,没有用上索引
创建索引:
db. articledb. createIndex( {"name" :1 })
再次查询测试:
db. articledb. find( {"name" :"zhangquandan" }) . explain ( )
观察结果可知,当前是使用的是使用索引name_1进行查询
12.聚合查询 12.1管道操作符 聚合管道操作是将文档在一个管道处理完毕后,把处理的结果传递给下一个管道进行再次处理。聚合管道是使用不同的管道阶段操作器进行不同聚合操作,管道阶段操作器也可称为管道操作符。
常见管道操作符:
类别
操作符
说明
分组
$group
将文档进行分组
限制
$limit
限制聚合管道返回的文档数
筛选
$match
用于过滤条件,只输出符合条件的文档
排序
$sort
对文档进行排序
投射
$project
修改文档结构(增加、删除字段)和名称
跳过
$skip
跳过指定数量的文档
$limit:用于限制MongoDB聚合管道返回的文档数
语法如下:
db. COLLECTION_NAME. aggregate( [ {$limit :整型数字}] ) . pretty( )
例如:查询前三条文档数据
db. user . aggregate( [ {$limit :3 }] )
**$match**:用于过滤数据,只输出符合条件的文档
语法如下:
db. COLLECTION_NAME. aggregate( [ {$match :{< key > :< value > }}] ) . pretty( )
例如:
db. user . aggregate( [ {$match :{"name" :"zhangsan" }}] )
**$sort**:将输入的文档先进行排序,再输出,-1表示降序,1表示升序。
语法如下:
db. COLLECTION_NAME. aggregate( [ {$sort:{< key > :- 1 或1 }}] ) . pretty( )
例如:
db. user . aggregate( [ {$sort:{"age" :1 }}] )
**$project**操作符:用于修改输入文档的结构(增加、删除字段等)和名称。
语法如下:
db. COLLECTION_NAME. aggregate( [ {$project:{< key > :< value > }}] ) . pretty( )
例如:
使用$project操作符,展示集合comment中的文档,并且文档均不包含字段_id
db. user . aggregate( [ {$project:{"_id" :0 }}] )
**$skip**操作符:在聚合管道中跳过指定数量的文档,并返回剩余的文档。
语法如下:
db. COLLECTION_NAME. aggregate( [ {$skip:整型数字}] ) . pretty( )
例如:
db. user . aggregate( [ {$skip:2 }] )
**$group**操作符:将集合中的文档进行分组,便于后续统计结果
语法如下:
db. COLLECTION_NAME. aggregate( [ {$group : { _id: < expression> , < field1> : { < accumulator1> : < expression1> }, . . . } }] ) . pretty( )
1._id+表达式 用来做分组条件,也就是_id后面的内容与sql中group by后面的表达式的用途相同
2._id后面的 字段+accumulator操作符与sql中做完group by后在select后面的的聚合函数用途相同,例如:sum()、avg()、max()、min()。
如:按照年龄进行分组
db. user . aggregate( [ {$group :{_id:"$age" }}] )
12.2管道表达式 管道阶段操作器的值被称为管道表达式,并且每个管道表达式都是一个文档结构,由字段名称、字段值和管道表达式组成。常见的管道表达式如下表。
$sum
语法如下:
db. COLLECTION_NAME. aggregate( [ {$group :{_id:"$< key1> ”
, < key2> :{$sum:“$< key3> ”}}}] ) . pretty( )
$avg
语法如下:
db. COLLECTION_NAME. aggregate ( [ {$group :{_id:"$< key1> ”
, < key2> :{$avg:“$< key3> ”}}}] ) . pretty( )
$min
db. COLLECTION_NAME. aggregate ( [ {$group :{_id:"$<key1>”
,<key2>:{$min:" $< key3> ”}}}] ) . pretty( )
$max
db. COLLECTION_NAME. aggregate ( [ {$group :{_id:"$< key1> ”
, < key2> :{$max:$< key3> }}}] ) . pretty( )
$push
语法如下:
db. COLLECTION_NAME. aggregate ( [ {$group :{_id:"$< key1> ”
, < key2> :{$push:$< key3> }}}] ) . pretty( )
$first
语法如下:
db. COLLECTION_NAME. aggregate ( [ {$group :{_id:"$< key1> ”
, < key2> :{$first :$< key4> }}}] ) . pretty( )
$last
语法如下:
db. COLLECTION_NAME. aggregate ( [ {$group :{_id:"$< key1> ” < key2> :{$last :$< key5> }}}] ) . pretty( )
2.8案例练习 2.8.1 文档简单操作1
创建newdb数据库
创建集合mycollection
db. createCollection( "mycollection" ) ;
在集合mycollection中插入数据
db. mycollection. insertOne( {
title: "MangoDB入门学习" ,
description: "MongoDB是一个NoSQL数据库" ,
by : "数据库" ,
tags: [ "MongoDB" , "DataBase" , "NoSQL" ]
})
将标题为”MangoDB入门学习”更新为”MangoDB实践”
db. mycollection. updateOne( {
"title" : "MangoDB入门学习"
}, {
$set : {
"title" : "MangoDB实践"
}
})
删除集合mycollection中的数据
db. myclollection. deleteMany( {})
删除集合mycollection
删除数据库newdb
2.8.2文档简单操作2
创建名称为自己姓名拼音缩写的数据库
在以自己姓名拼音缩写命名的数据库中创建集合students
db. createCollection( "students" )
在集合students中插入以下数据
db. students. insertMany( [ {
"name" : "Jim" ,
"age" : 25 ,
"email" : "75431457@qq.com" ,
"score" : {
"chinese" : 89 ,
"math" : 85 ,
"english" : 99
},
"country" : "USA" ,
"books" : [ "JS" , "C++" , "EXTJS" , "MongoDB" ]
}, {
"name" : "Tom" ,
"age" : 26 ,
"email" : "214551267@qq.com" ,
"score" : {
"chinese" : 75 ,
"math" : 77 ,
"english" : 95
},
"country" : "USA" ,
"books" : [ "PHP" , "JAVA" , "EXTJS" , "C++" ]
}, {
"name" : "Lily " ,
"age" : 24 ,
"email" : "344521234@qq.com" ,
"score" : {
"chinese" : 80 ,
"math" : 82 ,
"english" : 94
},
"country" : "USA" ,
"books" : [ "JS" , "JAVA" , "C#" , "MongoDB" ]
}, {
"name" : "李永" ,
"age" : 25 ,
"email" : "214556745@qq.com" ,
"score" : {
"chinese" : 96 ,
"math" : 94 ,
"english" : 90
},
"country" : "China" ,
"books" : [ "JS" , "JAVA" , "EXTJS" , "MongoDB" ]
}, {
"name" : "王敏" ,
"age" : 23 ,
"email" : "274524359@qq.com" ,
"score" : {
"chinese" : 99 ,
"math" : 96 ,
"english" : 97
},
"country" : "China" ,
"books" : [ "JS" , "C#" , "PHP" , "MongoDB" ]
}, {
"name" : "张力" ,
"age" : 22 ,
"email" : "232435456@qq.com" ,
"score" : {
"chinese" : 89 ,
"math" : 97 ,
"english" : 89
},
"country" : "China" ,
"books" : [ "JS" , "JAVA" , "C++" , "MongoDB" ]
}, {
"name" : "朴英俊" ,
"age" : 27 ,
"email" : "645434239@qq.com" ,
"score" : {
"chinese" : 36 ,
"math" : 46 ,
"english" : 55
},
"country" : "Korea" ,
"books" : [ "JS" , "JAVA" , "EXTJS" , "PHP" ]
}, {
"name" : "李贞贤" ,
"age" : 24 ,
"email" : "987555668@qq.com" ,
"score" : {
"chinese" : 35 ,
"math" : 75 ,
"english" : 64
},
"country" : "Korea" ,
"books" : [ "JS" , "C#" , "EXTJS" , "MongoDB" ]
}, {
"name" : "李慧英" ,
"age" : 26 ,
"email" : "435567778@qq.com" ,
"score" : {
"chinese" : 45 ,
"math" : 63 ,
"english" : 77
},
"country" : "Korea" ,
"books" : [ "JS" , "JAVA" , "EXTJS" , "MongoDB" ]
}] )
将李慧英的英语成绩修改为88
db. students. updateOne( {
"name" : "李慧英"
}, {
$set : {
"score.english" : 88
}
})
删除姓名是李贞贤的学生信息
db. students. deleteOne( {
"name" : "李贞贤"
})
将张力的书架上的第二本书修改为“C#”
db. students. updateOne( {
"name" : "张力"
}, {
$set : {
"books.1" : "C#"
}
})
给王敏的成绩中添加一门课“physical ”,成绩为89
db. students. update ( {
"name" : "王敏"
}, {
$set : {
"score.pyhsical" : 89
}
})
删除集合students
删除数据库stu
2.8.3文档简单操作3
统计中国学生的人数
db. students. find( {"country" :"China" }) . count ( ) ;
查询李姓学生的信息
db. students. find( {"name" :/ ^ 李/ }) ;
查询集合students中姓名为”王敏”的学生信息,结果中不显示_id,显示name,age
db. students. find( {"name" :"王敏" }, {"name" :1 , "age" :1 , "_id" :0 }) ;
查询语文成绩大于80小于95的文档
db. students. find( {"score.chinese" :{$gt:80 , $lt:95 }}) ;
查询书架上有“MongoDB”这本书的学生的姓名和年龄
db. students. find( {"books" :{$in :[ "MongoDB" ] }}, {"name" :1 , "age" :1 }) ;
查询书架上有“JAVA”或“JS”书的文档
db. students. find( {$or :[ {"books" :"JAVA" }, {"books" :"JS" }] }) ;
查询数学成绩小于60或大于90的学生的姓名
db. students. find( {$or :[ {"score.math" :{$lt:60 }}, {"score.math" :{$gt:90 }}] }, {"name" :1 , "_id" :0 }) ;
查询英语成绩在60到90之间的学生的信息
db. students. find( {$and :[ {"score.english" :{$gt:60 }}, {"score.english" :{$lt:90 }}] }) ;
查询书架上有4本书的学生的信息
db. students. find( {"books" : {$size: 4 }}) ;
查询国籍是“USA”和“China”的学生的姓名
db. students. find( {$or :[ {"country" :"China" }, {"country" :"USA" }] }, {"name" :1 , "_id" :0 }) ;
查询国籍是USA并且语文成绩大于80的学生的信息
db. students. find( {$and :[ {"country" :"USA" }, {"score.chinese" :{$gt:80 }}] }) ;
2.8.4文档聚合操作
查询软件技术和移动应用开发专业学生的平均年龄
db. students. aggregate( [ {$match : {major: {$in : [ "软件技术" , "移动应用开发" ] }}}, {
$group : {
_id: "$major" ,
age_avg: {$avg: {$toInt: "$age" }}
}
}] )
查看计算机应用技术专业的学生,并按照学分进行降序的排序
db. students. aggregate( [ {$match : {major: "计算机应用技术" }}, {$sort: {score: - 1 }}] ) ;
查看计算机应用技术专业男生和女生的总学分,最高学分和最低学分
db. students. aggregate( [
{$match : {major: "计算机应用技术" }},
{$group : {_id: "$sex" , total: {$sum: {$toInt: "$score" }}, max: {$max: "$score" }, min: {$min: "$score" }}}
] )
查询各个专业学生的平均成绩,第一个人的成绩和最后一个人的成绩
db. students. aggregate( [
{$group : {_id: "$major" , avg: {$avg: {$toInt: "$score" }}, first : {$first : "$score" }, last : {$last : "$score" }}}
] )
统计各个专业的学生人数并按人数从多到少排序
db. students. aggregate( [
{$group : {_id: "$major" , count: {$sum: 1 }}},
{$sort: {count: - 1 }}
] )
显示成绩排名第4和第5的学生的姓名,专业和成绩
db. students. aggregate( [
{$sort: {score: - 1 }},
{$skip: 3 },
{$limit : 2 },
{$project: {_id: 0 , name: 1 , major: 1 , score: 1 }}
] )
统计不同性别的学生姓名
db. students. aggregate( [
{$group : {_id: "$sex" , name: {$push: "$name" }}}
] )
查询年龄大于19的男生、女生人数
db. students. aggregate( [ {$match : {$expr: {"age" : {$gt: [ {$toInt: "$age" }, 19 ] }}}}, {$group : {_id: "$sex" , "人数" : {$sum: 1 }}}] )
2.8.5索引操作
在集合students的字段age上创建单字段索引,并指定顺序为降序
db. students. createIndex( {age: - 1 }, {name: "age_index" }, {background: true })
在集合students的字段major和字段credits上创建复合索引,指定字段major 为升序,字段credits为降序
db. students. createIndex( {major: 1 , credits: - 1 })
查询数据库stu中集合students的索引
删除集合students字段age上的单字段索引
db. students. dropIndex( "age_index" )
删除集合students中的所有索引
db. students. dropIndexes( )
2.8.6安全与访问控制
在admin数据库中创建管理员用户“useradmin”,密码为“123456”,拥有userAdminAnyDatabase角色
db. createUser( {user :"useradmin" , pwd:"123456" , roles:[ {role:"userAdminAnyDatabase" , db:"admin" }] })
开启用户访问控制:修改配置文件mongod.cfg,重启MongoDB服务
使用管理员账户useradmin在数据库admin中创建一个用户“sturead”,密码“123456”,并且该用户只具有stu数据库的read权限
db. createUser( {
user : "sturead" ,
pwd: "123456" ,
roles: [ {
role: "read" ,
db: "admin"
}]
})
查看用户信息
查看用户权限
db. getUser( 用户名, {showPrivileges:true })
修改用户信息
db. updateUser( "itcastUser" , {roles:[ {role:"read" , db:“articledb"},
{role:" readAnyDatabase",db:" admin"}] })
删除用户角色
db. revokeRolesFromUser( 用户名, [ {role:"readAnyDatabase" , db:"admin" }] )
修改用户密码
db. changeUserPassword( 用户名, 密码)
删除用户
13.副本集 **MongoDB 副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或多个Secondary节点组成。 **副本集没有固定的主节点,当主节点发生故障时整个集群会选举一个主节点为系统提供服务以保证系统的高可用。注意:这种方式并不能解决主节点的单点访问压力问题。
Automatic Failover 自动故障转移机制: 当主节点未与集合的其他成员通信超过配置的选举超时时间(默认为 10 秒)时,合格的辅助节点将调用选举以将自己提名为新的主节点。集群尝试完成新主节点的选举并恢复正常操作。
搭建副本集
- mkdir - p . . / repl/ data1
- mkdir - p . . / repl/ data2
- mkdir - p . . / repl/ data3
$ mongod
$ mongod
$ mongod
注意: –replSet 副本集 myreplace 副本集名称/集群中其他节点的主机和端口
var config = {
_id:"myreplace" ,
members:[
{_id:0 , host:"121.5.167.13:27017" },
{_id:1 , host:"121.5.167.13:27018" },
{_id:2 , host:"121.5.167.13:27019" }]
}
rs. initiate( config) ;
> rs. slaveOk( ) ; 旧的
> rs. secondaryOk( ) ; 新的
注意: 当MongoDB副本集架构只剩一个节点时,整个节点是不可用的。单主不可写。
14.分片集群 有副本集为什么要使用分片集群呢?
副本集的特点是主从复制,实现故障的自动转移和架构高可用,能够对数据进行冗余备份。
但是不能够解决单点压力、并发访问压力问题,即数据的读写都要在主节点操作。
==分片(sharding)是指将数据拆分,将其分散存在不同机器的过程,有时也用分区(partitioning)来表示这个概念,==将数据分散在不同的机器上,不需要功能强大的大型计算机就能存储更多的数据,处理更大的负载。
分片目的是通过分片能够增加更多机器来应对不断的增加负载和数据,还不影响应用运行。
MongoDB支持自动分片,可以摆脱手动分片的管理困扰,集群自动切分数据做负载均衡。
**MongoDB分片的基本思想就是将集合拆分成多个块,这些块分散在若干个片里,每个片只负责总数据的一部分,应用程序不必知道哪些片对应哪些数据,甚至不需要知道数据拆分了 **,所以在分片之前会运行一个路由进程,mongos进程,这个路由器知道所有的数据存放位置,应用只需要直接与mongos交互即可。mongos自动将请求转到相应的片上获取数据,从应用角度看分不分片没有什么区别。
分片集群架构
Shard: 用于存储实际的数据块,实际生产环境中一个shard server角色可由几台机器组个一个replica set承担,防止主机单点故障
Config Server:mongod实例 ,存储了整个 ClusterMetadata。
Query Routers: 前端路由 ,客户端由此接入,且让整个集群看上去像单一数据库,前端应用可以透明使用。
Shard Key: 片键 ,**设置分片时需要在集合中选一个键,用该键的值作为拆分数据的依据,这个片键称之为(shard key),片键的选取很重要,片键的选取决定了数据散列是否均匀 **。
集群环境搭建
- Shard Server 1 :27017
- Shard Repl 1 :27018
- Shard Server 2 :27019
- Shard Repl 2 :27020
- Shard Server 3 :27021
- Shard Repl 3 :27022
- Config Server :27023
- Config Server :27024
- Config Server :27025
- Route Process :27026
- mkdir - p . . / cluster/ shard/ s0
- mkdir - p . . / cluster/ shard/ s0- repl
- mkdir - p . . / cluster/ shard/ s1
- mkdir - p . . / cluster/ shard/ s1- repl
- mkdir - p . . / cluster/ shard/ s2
- mkdir - p . . / cluster/ shard/ s2- repl
- mkdir - p . . / cluster/ shard/ config1
- mkdir - p . . / cluster/ shard/ config2
- mkdir - p . . / cluster/ shard/ config3
> . / mongod
> . / mongod
config = { _id:"r0" , members:[
{_id:0 , host:"121.5.167.13:27017" },
{_id:1 , host:"121.5.167.13:27018" },
]
}
rs. initiate( config) ;
> . / mongod
> . / mongod
config = { _id:"r1" , members:[
{_id:0 , host:"121.5.167.13:27019" },
{_id:1 , host:"121.5.167.13:27020" },
]
}
rs. initiate( config) ;
> . / mongod
> . / mongod
config = { _id:"r2" , members:[
{_id:0 , host:"121.5.167.13:27021" },
{_id:1 , host:"121.5.167.13:27022" },
]
}
rs. initiate( config) ;
> . / mongod
> . / mongod
> . / mongod
- ` 登录任意节点 congfig server`
> 1. use admin
> 2. 在admin中执行
config = {
_id:"config" ,
configsvr: true ,
members:[
{_id:0 , host:"121.5.167.13:27023" },
{_id:1 , host:"121.5.167.13:27024" },
{_id:2 , host:"121.5.167.13:27025" }
]
}
> 3. rs. initiate( config) ;
> . / mongos
> 1. 登录 mongo
> 2. use admin
> 3. 添加分片信息
db. runCommand( { addshard:"r0/121.5.167.13:27017,121.5.167.13:27018" ,
"allowLocal" :true }) ;
db. runCommand( { addshard:"r1/121.5.167.13:27019,121.5.167.13:27020" ,
"allowLocal" :true }) ;
db. runCommand( { addshard:"r2/121.5.167.13:27021,121.5.167.13:27022" ,
"allowLocal" :true }) ;
> 4. 指定分片的数据库
db. runCommand( { enablesharding:"baizhi" }) ;
> 5. 设置库的片键信息
db. runCommand( { shardcollection: "baizhi.users" , key : { _id:1 }}) ;
db. runCommand( { shardcollection: "baizhi.emps" , key : { _id: "hashed" }})
13.SpringBoot集成Mongodb 13.1环境搭建
引入pom依赖
< dependency>
< groupId> org.springframework.boot</ groupId>
< artifactId> spring-boot-starter-data-mongodb</ artifactId>
</ dependency>
配置文件
spring :
data :
mongodb :
database : test
host : localhost
port : 27017
username : root
password : 123456
authentication-database : admin
uri : mongodb: //admin: 123456@localhost: 27017/test? authSource=admin
uri : mongodb: //admin: 123456@localhost: 27017 , localhost: 27018 , localhost: 27019/test? authSource=admin
使用时注入mongoTemplate
mongodbTemplate 官网api
13.2创建删除集合 @Resource
private MongoTemplate mongoTemplate;
@Test
public void testCreate ( ) {
if ( mongoTemplate. collectionExists ( "mongodbTest" ) ) {
System . out. println ( "collection exists" ) ;
return ;
}
mongoTemplate. createCollection ( "mongodbTest" ) ;
System . out. println ( "collection created successfully" ) ;
}
@Test
public void testDrop ( ) {
if ( mongoTemplate. collectionExists ( "mongodbTest" ) ) {
mongoTemplate. dropCollection ( "mongodbTest" ) ;
System . out. println ( "collection dropped" ) ;
} else {
System . out. println ( "collection not exists" ) ;
}
}
13.3添加文档 相关注解:
@Document 对应 类
修饰范围: 用在类上
作用: 用来映射这个类的一个对象为 mongo 中一条文档数据
属性:(value 、collection )用来指定操作的集合名称
@Id 对应 要指定为_id的变量名
修饰范围: 用在成员变量、方法上,只能出现一次
作用: 用来将成员变量的值映射为文档的_id 的值
@Field 对应 剩余变量名(变量名都按照类中属性名定义时,可以不指定,即同名时可不指定)
修饰范围: 用在成员变量、方法上
作用: 用来将成员变量以及值映射为文档中一个key、value对
属性: ( name,value)用来指定在文档中 key 的名称,默认为成员变量名
@Transient 不参与文档转换
修饰范围: 用在成员变量、方法上
作用 : 用来指定改成员变量,不参与文档的序列化
MongoDB
https://xhablog.online/2023/02/27/MongoDB基础操作/
博客在允许 JavaScript 运行的环境下浏览效果更佳