MongoDB学习笔记

MongoDB学习笔记

  • 一 安装与卸载
    • 1.1 配置存储库
    • 1.2 安装MongoDB Enterprise软件包
    • 1.3 启动
    • 1.4 通过命令行窗口连接后简单使用
    • 1.5 停止MongoDB
    • 1.6 卸载
    • 1.7 修复
  • 二 通过命令行mongo管理MongoDB
    • 2.1 连接
    • 2.2 自定义提示
      • 2.2.1 自定义提示以显示操作数
      • 2.2.2 自定义提示以显示数据库和主机名
      • 2.2.3 自定义提示以显示时间和文档计数
    • 2.3 使用外部编译器
    • 2.4 修改查询操作返回的结果条数
    • 2.5 帮助命令
    • 2.6 执行JavaScript
  • 三 CRUD
    • 3.1 插入
    • 3.2 查询
      • 3.2.1 普通查询
      • 3.2.2 查询数组
      • 3.2.3 指定查询返回结果的字段
      • 3.2.4 null查询
      • 3.2.5 分页
      • 3.2.6 排序
      • 3.2.7 手动迭代游标查询
      • 3.2.8 聚合查询
    • 3.3 更新
      • 3.3.1 更新
      • 3.3.2 替换
      • 3.3.3 其他
    • 3.4 删除
      • 3.4.1 删除文件
    • 3.5 批量写入操作
    • 3.6 文本搜索
      • 3.6.1 创建文本索引
      • 2.6.2 搜索
  • 四 聚合操作
    • 4.1 聚合管道
    • 4.2 单一目的聚合操作
  • 五 安全
    • 5.1 SCRAM 认证
      • 5.1.1 用户
        • 5.1.1.1 创建管理员
        • 5.1.1.2 创建普通用户
        • 5.1.1.3 查看用户
        • 5.1.1.4 用户操作命令
      • 5.1.2 角色
        • 5.1.2.1 内置角色
        • 5.1.2.2 自定义角色
        • 5.1.2.3 角色管理命令
      • 5.1.3 开启安全鉴权模式
      • 5.1.4 通过用户密码连接MongoDB
    • 5.2 其他认证方式
    • 5.3 集合级访问控制
  • 六 主从复制
  • 七 分片
  • 八 MongoDB Compass(可视化工具)
    • 8.1 下载
    • 8.2 连接
  • 九 集成springboot

MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系据库单表查询的绝大部分功能,而且还支持对数据建立索引。

MongoDB学习笔记_第1张图片

一 安装与卸载

在Red Hat或CentOS上安装MongoDB企业版-官网文档

以下为通过yum在CentOS安装MongoDB-5.0企业版

1.1 配置存储库

  1. 创建一个 /etc/yum.repos.d/mongodb-enterprise-5.0.repo文件

    vim /etc/yum.repos.d/mongodb-enterprise-5.0.repo
    
  2. 在文件中写入以下内容

    [mongodb-enterprise-5.0]
    name=MongoDB Enterprise Repository
    baseurl=https://repo.mongodb.com/yum/redhat/$releasever/mongodb-enterprise/5.0/$basearch/
    gpgcheck=1
    enabled=1
    gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc
    

1.2 安装MongoDB Enterprise软件包

sudo yum install -y mongodb-enterprise

1.3 启动

systemctl start mongod
# 通过配置文件启动
/usr/bin/mongod -f /etc/mongod.conf

1.4 通过命令行窗口连接后简单使用

命令-官方文档

mongosh  # 连接数据库
db # 查看当前数据库
show dbs  # 显示所有数据库
use test  # 使用test数据库,没有就创建
show collections  # 显示所有集合
show tables  # 显示所有表
db.inventory.insertMany([
   { item: "journal", qty: 25, status: "A", size: { h: 14, w: 21, uom: "cm" }, tags: [ "blank", "red" ] },
   { item: "notebook", qty: 50, status: "A", size: { h: 8.5, w: 11, uom: "in" }, tags: [ "red", "blank" ] },
   { item: "paper", qty: 10, status: "D", size: { h: 8.5, w: 11, uom: "in" }, tags: [ "red", "blank", "plain" ] },
   { item: "planner", qty: 0, status: "D", size: { h: 22.85, w: 30, uom: "cm" }, tags: [ "blank", "red" ] },
   { item: "postcard", qty: 45, status: "A", size: { h: 10, w: 15.25, uom: "cm" }, tags: [ "blue" ] }
]);  # 插入多条数据
db.insertMany.find({}).pretty()  #查询所有后格式化输出
db.inventory.find( { status: "D" } ).pretty();  # 查询 status = D
db.inventory.find( { qty: 0 } ).pretty();  # 查询 qty = 0
db.inventory.find( { qty: 0, status: "D" } ).pretty();  # 查询 qty = 0 并且 status = D
db.inventory.find( { "size.uom": "in" } ).pretty();  # 查询 size 里面 uom = in
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } ).pretty();  # 查询 size 中 h =14 并且 w = 21 并且 uom = cn
db.inventory.find( { tags: "red" } ).pretty();  # 查询 tags 中包含 red
db.inventory.find( { tags: [ "red", "blank" ] } ).pretty();  # 查询 tage 为 [ "red", "blank" ]
db.inventory.find( { }, { item: 1, status: 1 } ).pretty();  # 查询结果只返回 item 和 status,1表示要返回的,_id 默认返回
db.inventory.find( {}, { _id: 0, item: 1, status: 1 } ).pretty();  # 0表示不返回的
db.inventory.drop()  # 删除user表
db.dropDatabase()  # 删除当前数据库
exit

1.5 停止MongoDB

systemctl stop mongod
# 通过管理员调用shutdown方法关闭
mongosh
use admin
db.shutdownServer()

1.6 卸载

  1. 删除软件包

    sudo yum erase $(rpm -qa | grep mongodb-enterprise)
    
  2. 删除数据目录

    sudo rm -r /var/log/mongodb
    sudo rm -r /var/lib/mongo
    

1.7 修复

MongoDB不正当停止可能会造成损坏,导致无法启动

vim /etc/mongod.conf  # 打开配置文件,查看数据库与日志路径
rm /var/lib/mongo/mongod.lock
rm /var/log/mongodb/mongod.log
/usr/bin/mongod -f /etc/mongod.conf --repair

二 通过命令行mongo管理MongoDB

官方文档

2.1 连接

  • 连接本地默认端口

    mongosh
    
  • 连接单个

    mongosh "mongodb://用户名@IP:端口/?authSource=数据库"
    
    mongosh --username 用户名 --password --authenticationDatabase 数据库 --host IP --port 端口
    
  • 连接集群

    mongosh "mongodb://IP:端口,IP:端口,IP:端口/?replicaSet=集群名&ssl=true"
    
    mongosh  "mongodb+srv://域名"
    
    mongosh  --ssl --host 集群名/IP:端口,IP:端口,IP:端口
    

2.2 自定义提示

2.2.1 自定义提示以显示操作数

mongo连接后执行

cmdCount = 1;
prompt = function() {
    return (cmdCount++) + "> ";
}

MongoDB学习笔记_第2张图片

2.2.2 自定义提示以显示数据库和主机名

mongo连接后执行

host = db.serverStatus().host;
prompt = function() {
    return db+"@"+host+"$ ";
}

MongoDB学习笔记_第3张图片

2.2.3 自定义提示以显示时间和文档计数

mongo连接后执行

prompt = function() {
    return "Uptime:"+db.serverStatus().uptime+" Documents:"+db.stats().objects+" > ";
}

MongoDB学习笔记_第4张图片

2.3 使用外部编译器

  1. 在mongo连接之前,设置 EDITOR 环境变量

    export EDITOR=vim
    mongosh
    
  2. 定义函数

    function myFunction () { }
    
  3. 打开编辑器编写函数

    edit myFunction
    
    function myFunction() {
        print("This was edited");
    }
    
  4. 查看

    myFunction
    

    MongoDB学习笔记_第5张图片

2.4 修改查询操作返回的结果条数

默认为20,可以在连接后通过以下命令修改

DBQuery.shellBatchSize = 3;

MongoDB学习笔记_第6张图片

2.5 帮助命令

  • 连接前

    mongosh -h
    mongosh --help
    

    MongoDB学习笔记_第7张图片

  • 连接后
    在后面追加上help()方法
    MongoDB学习笔记_第8张图片

2.6 执行JavaScript

  • 执行片段

    mongosh test --eval "printjson(db.getCollectionNames())"  # 查询数据库 test 中集合的名称
    
  • 执行脚本

    mongosh localhost:27017/test myjsfile.js  # 执行 myjsfile.js
    

三 CRUD

3.1 插入

官方文档

执行插入操作时,如果该集合当前不存在,则插入操作将创建该集合。

在MongoDB中,存储在集合中的每个文档都需要一个唯一的 _id字段作为主键。如果插入的文档省略了该_id字段,则MongoDB驱动程序会自动为该字段生成一个ObjectId_id。这也适用于通过upsert:true的更新操作插入的文档。

MongoDB中的所有写操作在单个文档级别上都是原子性的

  • 插入一个文档

    db.inventory.insertOne(
       { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
    )
    
  • 插入多个文件

    db.inventory.insertMany([
       { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
       { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
       { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
    ])
    
  • 插入任意个文件

    db.inventory.insert([
       { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
       { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
       { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
    ])
    
  • db.collection.update()与upsert: true 选项一起使用时。

  • db.collection.updateOne()与upsert: true选项一起使用时。

  • db.collection.updateMany()与upsert: true选项一起使用时。

  • db.collection.findAndModify()与upsert: true选项一起使用时。

  • db.collection.findOneAndUpdate()与upsert: true选项一起使用时 。

  • db.collection.findOneAndReplace()与upsert: true选项一起使用时 。

  • db.collection.save()。

  • db.collection.bulkWrite()。

3.2 查询

官方文档

MongoDB学习笔记_第9张图片

MongoDB学习笔记_第10张图片

查询内容输出格式化使用 pretty()

3.2.1 普通查询

  • 查询集合中的所有文档

    db.inventory.find( {} )
    
  • 完全匹配查询

    db.inventory.find( { status: "D" } )
    
  • 与(默认、省略)查询

     ```powershell
     db.inventory.find( { status: "A", qty: { $lt: 30 } } )
     ```
    
  • in

    db.inventory.find( { status: { $in: [ "A", "D" ] } } )
    
  • 或查询

    db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
    
  • 查询数组中包含某一个

    db.inventory.find( { tags: "red" } )
    
  • 查询数组中同时包含多个

    db.inventory.find( { tags: { $all: ["red", "blank"] } } )
    
  • 查询数组中至少有一个值大于25的

    db.inventory.find( { dim_cm: { $gt: 25 } } )
    
  • 查询一个元素可以满足大于15 条件,而另一个元素可以满足小于20 条件,或者一个元素可以满足以下两个条件

    db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
    

3.2.2 查询数组

  • 查询数组包含至少一个同时大于( g t ) 22 和 小 于 ( gt) 22和小于( gt22lt)30的元素:

    db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )
    
  • 查询数组dim_cm中第二个元素大于25的所有文档:

    db.inventory.find( { "dim_cm.1": { $gt: 25 } } )
    
  • 查询数组tags有3个元素(长度/大小等于3)的文档

    db.inventory.find( { "tags": { $size: 3 } } )
    

3.2.3 指定查询返回结果的字段

_id默认返回;
要返回的字段设置为1;
不返回的字段设置为0;
  • 返回item,status与_id

    db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
    
  • 返回item,status

    db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
    
  • 返回除status和instock的所有字段

    db.inventory.find( { status: "A" }, { status: 0, instock: 0 } )
    
  • 返回内嵌文件的特定字段

    db.inventory.find(
       { status: "A" },
       { item: 1, status: 1, "size.uom": 1 }
    )
    
  • tags数组只返回从下标0开始的1个

    db.inventory.find(
       { item: "journal" },
       { tags: {$slice: 1} }
    )
    
  • tags数组只返回从下标1开始的2个

    db.inventory.find(
       { item: "paper" },
       { tags: {$slice: [1, 2]} }
    )
    
  • tags数组只返回从右向左数第3个开始,向右取2个

    db.inventory.find(
       { item: "paper" },
       { tags: {$slice: [-3, 2]} }
    )
    

3.2.4 null查询

  • 查询item为null或不存在的(三个语句效果相同)

    db.inventory.find( { item: null } )
    db.inventory.find( { item : { $type: 10 } } )  # 官方文档说可以这样用,但实际不行,查询没有返回结果
    db.inventory.find( { item : { $exists: false } } )
    

3.2.5 分页

跳过一行,从第二行开始查询两条数据

db.inventory.find({}).skip(1).limit(2)

3.2.6 排序

根据size数组里面的h排序,1是升序,-1降序

db.inventory.find({}).sort({"size.h": 1})

3.2.7 手动迭代游标查询

默认情况下,服务器将在闲置10分钟后或客户端用尽游标后自动关闭游标。
# 遍历打印所有
var myCursor = db.users.find( { type: 2 } );
while (myCursor.hasNext()) {
   printjson(myCursor.next());
}

var myCursor =  db.users.find( { type: 2 } );
myCursor.forEach(printjson);

# 转化为数组,打印下表为3的数据
var myCursor = db.inventory.find( { type: 2 } );
var documentArray = myCursor.toArray();
var myDocument = documentArray[3];
printjson(myDocument);

# 打印下表为1的数据
var myCursor = db.users.find( { type: 2 } );
var myDocument = myCursor[1];
printjson(myDocument);

3.2.8 聚合查询

  • 过滤重复的数据

    db.inventory.distinct( { status: "D" } )
    
  • 查询符合条件的数据的条数

    db.inventory.countDocuments( { status: "D" } )
    
  • 估算条数,没有countDocuments精确

    db.inventory.estimatedDocumentCount({})
    

3.3 更新

官方文档

MongoDB中的所有写操作在单个文档级别上都是原子性的。

_id无法修改,并且_id字段永远是文档中的第一个字段

除修改字段名,更新操作不会对文档中字段进行重排序

更新操作符

运算符 样例 描述
$inc {$inc:{qty:20}} qty字段值加20,字段不存在就新增一个默认值为0的,然后加20;如果值为负数则相当于减;用于整型,长整型,双精度浮点型
$set {$set:{qty:10}} qty字段值设为10,字段不存在时则新增字段,并且不受类型限制
$unset {$unset:{aaa:true}} 删除字段aaa
$rename {$rename:{aaa: “bbb”}} 把字段aaa改为bbb,可同时修改多个;如果修改后的字段名在文档中已存在,就会覆盖以前的;同时还可以达到将字段在文档与子文档之间移动的效果
$setOnInsert {$setOnInsert: {qty: 30}}, {upsert: true} 与upsert一起使用,只有新增文档时才会生效,将qty设置为30
$currentDate {$currentDate:{lastUpdate:true}} 将字段lastUpdate设为当前时间
$min {$min:{qty:10}} 如果字段qty的值小于10,就将字段qty的值设置为10
$max {$max:{qty:10}} 如果字段qty的值大于10,就将字段qty的值设置为10
$mul {$mul:{qty:10}} 将字段qty的值乘以10
$ {$ set: {“lengths.$ [element]”: 100}}, {arrayFilters: [{“element”: {$gte: 100}}]} 定位到某一个元素,lengths数组中大于100的元素
$push {$push:{tags:“B”}} 添加“”B“”到数组tags中
$addToSet {$addToSet:{tags:“B”}} 如果数组tags中没有“”B“”,则添加“”B“”到数组中
$pop {$pop: {tags: -1}} -1为删除数组tags左边第一个,1为删除最后右边第一个,只能为1或-1
$pull {$pull: {tags: “B”}} 删除数组tags中所有的“”B“”
$pullAll {$pullAll: {tags: [“B”, “C”]}} 从数组tags中删除所有的“”B“”,“”C“”
$each {$push: {tags: {$each: [“D”, “E”, “F”]}}} 将"D", “E”, "F"每个都作为一个单独的个体,一次性加入tags数组中。如果没用$each,会把 [“D”, “E”, “F”]作为一个整体加入tags数组中;与 $push、 $addToSet一起使用
$slice {$push: {tags: {$each: [“D”, “E”, “F”], $slice: 8}}}) 切割,从左边(头)开始取8位,负数为从右边(后)开始;与$push、 $addToSet、 $each一起使用,保证数组长度
$sort {$push: {aaa: {$each:[],$sort:{score:1}}}} 数组aaa根据字段score升序排序
$bit 位更新

3.3.1 更新

官方文档

  • db.collection.update()

  • db.collection.updateOne()

  • db.collection.updateMany()

    db.collection.update(
       <filter>,  # 查询条件,根据查询条件找出要修改的文档,传{}空表示更新第一个文档
       ,  # 更新操作
       {
         upsert: ,  # 默认false,true是当没有匹配的文档是创建一个新的
         writeConcern: ,  # 写策略
         collation: ,  # 索引语音规则
         arrayFilters: [ , ... ],  # 过滤文档数组,用于确定更新操作要修改的数组中的具体元素
         hint:  |string>  # 指定查询希望使用的索引字段,如果索引不存在会报错
         multi:   # 默认false,只更新第一个文档,true更新所有符合条件的文档。updateOne、updateMany就是这个的默认值不同
       }
    )
    
    db.inventory.drop()
    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" }
    ] );
    

    对于 u n s e t , unset, unsetcurrentDate等操作符对应的的bson中字段名作为key值,value值可以为任意值

    db.inventory.update({}, {$set:{qty:200}})
    db.inventory.update({item:"paper"},{$set:{qty:10}})
    db.inventory.update({item:"paper"},{$inc:{qty:20}})
    db.inventory.update({item:"paper"},{$inc:{qty:-20}})
    db.inventory.update({item:"paper"},{$mul:{qty:10}})
    db.inventory.update({item: "paper"}, {$setOnInsert: {qty: 30}})
    db.inventory.update({item:"paper"},{$currentDate:{lastUpdate: true}})
    db.inventory.update({item:"paper"},{$rename:{lastUpdate: "lastModify"}})
    db.inventory.update({item: "paper"}, {$rename: {"size.h": "h"}})
    db.inventory.update({item:"paper"},{$unset:{lastModify:true}}) 
    db.inventory.update({item:"aaa"},{$currentDate:{lastUpdate:true}})
    db.inventory.update({item:"aaa"},{$currentDate:{lastUpdate:true}},{upsert:true})
    db.inventory.update({item:"aaa"},{$set:{tags:["A","B"]}})
    db.inventory.update({item:"aaa"},{$push:{tags:"B"}})
    db.inventory.update({item: "aaa"}, {$push: {tags: {$each: ["D", "E", "F"]}}})
    db.inventory.update({item: "aaa"}, {$push: {tags: {$each: ["D", "E", "F"], $slice: 8}}})
    db.inventory.update({item:"aaa"},{$addToSet:{tags:"B"}})
    db.inventory.update({item:"aaa"},{$addToSet:{tags:"C"}})
    db.inventory.update({item: "aaa"}, {$pop: {tags: -1}})  # 删除第一个
    db.inventory.update({item: "aaa"}, {$pop: {tags: 1}})  # 删除最后一个
    db.inventory.update({item: "aaa"}, {$pull: {tags: "B"}})
    db.inventory.update({item: "aaa"}, {$pullAll: {tags: ["B", "C"]}})
    db.inventory.update({item: "aaa"}, {$set: {"lengths.$[element]": 100}}, {arrayFilters: [{"element": {$gte: 100}}]})  # 将length数组中大于100的值改为100
    

3.3.2 替换

  • db.collection.replaceOne()

    db.collection.replaceOne(
       <filter>,  # 查询条件,根据查询条件找出要替换的文档,传{}空表示替换第一个文档
       ,  # 替换的文档
       {
         upsert: ,  # 默认false,true是当没有匹配的文档是创建一个新的
         writeConcern: ,  # 写策略
         collation: ,  # 索引语音规则
         hint: |string>   # 指定查询希望使用的索引字段,如果索引不存在会报错
       }
    )
    
    db.inventory.replaceOne({item:"canvas"},{item: "aaa"})
    

3.3.3 其他

  • db.collection.findOneAndReplace()。
  • db.collection.findOneAndUpdate()。
  • db.collection.findAndModify()。
  • db.collection.save()。
  • db.collection.bulkWrite()。

3.4 删除

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

3.4.1 删除文件

  1. 删除所有文件

    db.inventory.deleteMany({})
    
  2. 删除符合条件的所有文件

    db.inventory.deleteMany({ status : "A" })
    
  3. 删除符合条件的一个文档(第一个)

    db.inventory.deleteOne( { status: "D" } )
    
  4. 移除
    可以自定义删除一行还是所有,可以自定义写关注,可以对匹配到的要删除的数据进行排序等。
    官方文档

    db.collection.remove(
       ,
       {
         justOne: ,
         writeConcern: ,
         collation: ,
         let:  // Added in MongoDB 5.0
       }
    )
    
  5. 排序后删除并返回第一个

    db.collection.findOneAndDelete( filter, options )
    
  6. 排序后修改第一个文档,并返回原来的第一个文档

    db.collection.findAndModify({
        query: ,
        sort: ,
        remove: ,
        update: , // Changed in MongoDB 4.2
        new: ,
        fields: ,
        upsert: ,
        bypassDocumentValidation: ,
        writeConcern: ,
        collation: ,
        arrayFilters: [ , ... ],
        let:  // Added in MongoDB 5.0
    });
    

3.5 批量写入操作

官方文档

db.collection.bulkWrite() 方法提供了执行批量插入、更新和删除操作的能力。并且插入、更新、删除可以一起执行。

使用有序的操作列表,MongoDB 以串行方式执行操作。如果在处理其中一个写操作的过程中发生错误,MongoDB 将返回而不处理列表中任何剩余的写操作。
使用无序列表的操作,MongoDB 可以并行执行操作,但不能保证这种行为。如果在处理其中一个写操作的过程中发生错误,MongoDB 将继续处理列表中剩余的写操作。
默认情况下使用有序操作。要使用无序操作,设置 ordered : false。

示例:

try {
   db.characters.bulkWrite(
      [
         { insertOne :
            {
               "document" :
               {
                  "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4
               }
            }
         },
         { insertOne :
            {
               "document" :
               {
                  "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3
               }
            }
         },
         { updateOne :
            {
               "filter" : { "char" : "Eldon" },
               "update" : { $set : { "status" : "Critical Injury" } }
            }
         },
         { deleteOne :
            { "filter" : { "char" : "Brisbane" } }
         },
         { replaceOne :
            {
               "filter" : { "char" : "Meldane" },
               "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 }
            }
         }
      ]
   );
}
catch (e) {
   print(e);
}

3.6 文本搜索

官方文档

对索引字段的内容进行搜索。

要使用文本搜索,必须先创建文本索引。一个集合只能有一个文本搜索索引,但该索引可以覆盖多个字段。

3.6.1 创建文本索引

为集合 stores 创建文本搜索索引(text),索引包括 name、description 两个字段,即从这两个字段的内容中搜索。

db.stores.createIndex( { name: "text", description: "text" } )

2.6.2 搜索

db.stores.find( { $text: { $search: "java coffee shop" } } )  # 单词搜索,空格分隔
db.stores.find( { $text: { $search: "\"coffee shop\"" } } )  # 短语搜索,用双引号包裹,\ 反斜杠转义
db.stores.find( { $text: { $search: "java shop -coffee" } } )  # 通过 - 杠排除
db.stores.find(
   { $text: { $search: "java coffee shop" } },
   { score: { $meta: "textScore" } }
).sort( { score: { $meta: "textScore" } } )  # 排序,根据分数排序,默认不排序

四 聚合操作

聚合操作处理多个文档并返回计算结果。比如分组求和等

4.1 聚合管道

官方文档

db.orders.aggregate( [
   { $match: { status: "urgent" } },
   { $group: { _id: "$productName", sumQuantity: { $sum: "$quantity" } } }
] )
  • $match:匹配,即找到集合 orders 中所有字段 status 的值为 urgent 的文档。
  • $group:分组。对 $match 中匹配到的文档,根据字段 productName 进行分组。
  • $sum:求和。对分组后的文档,对字段 quantity 求和

4.2 单一目的聚合操作

通过其他收集方法实现

五 安全

5.1 SCRAM 认证

官方文档

Salted Challenge Response Authentication Mechanism (SCRAM)是 MongoDB 的默认身份验证机制。

5.1.1 用户

用户创建官方文档

5.1.1.1 创建管理员
use admin
db.createUser(
  {
    user: "root",
    pwd: passwordPrompt(), // 也可以直接写密码,但不够安全。passwordPrompt() 可以打开密码输入模式
    roles: [
      { role: "root", db: "admin" }
    ]
  }
)
db.createUser(
  {
    user: "admin",
    pwd: passwordPrompt(), // 也可以直接写密码,但不够安全。passwordPrompt() 可以打开密码输入模式
    roles: [
      { role: "userAdminAnyDatabase", db: "admin" },
      { role: "readWriteAnyDatabase", db: "admin" }
    ]
  }
)
5.1.1.2 创建普通用户
use test
db.createUser(
  {
    user: "myTester",
    pwd:  passwordPrompt(),   // or cleartext password
    roles: [ { role: "readWrite", db: "test" },
             { role: "read", db: "reporting" } ]
  }
)
5.1.1.3 查看用户

查看admin数据库中的system.user集合

use admin
db.system.users.find()
db.system.users.find({user: "admin"})
5.1.1.4 用户操作命令
命令 注释
createUser 创建一个新用户。
dropAllUsersFromDatabase 删除与数据库关联的所有用户。
dropUser 删除单个用户。
grantRolesToUser 向用户授予角色及其权限。
revokeRolesFromUser 从用户中删除角色。
updateUser 更新用户的数据。
usersInfo 返回有关指定用户的信息。
db.auth() 向数据库验证用户。
db.changeUserPassword() 更改现有用户的密码。
db.dropAllUsers() 删除与数据库关联的所有用户。
db.getUser() 返回有关指定用户的信息。
db.getUsers() 返回有关与数据库关联的所有用户的信息。
passwordPrompt() 提示输入密码作为在各种mongosh用户身份验证/管理方法中直接指定密码的替代方法。

5.1.2 角色

5.1.2.1 内置角色

内置角色官方文档

5.1.2.2 自定义角色

官方文档

5.1.2.3 角色管理命令
命令 注释
createRole 创建角色并指定其权限。
dropRole 删除用户定义的角色。
dropAllRolesFromDatabase 从数据库中删除所有用户定义的角色。
grantPrivilegesToRole 为用户定义的角色分配权限。
grantRolesToRole 指定用户定义的角色从中继承特权的角色。
invalidateUserCache 刷新用户信息的内存缓存,包括凭据和角色。
revokePrivilegesFromRole 从用户定义的角色中删除指定的权限。
revokeRolesFromRole 从用户定义的角色中删除指定的继承角色。
rolesInfo 返回指定角色的信息。
updateRole 更新用户定义的角色。
db.getRole() 返回指定角色的信息。
db.getRoles() 返回数据库中所有用户定义角色的信息。

5.1.3 开启安全鉴权模式

修改配置文件 /etc/mongod.conf(默认),添加:

security:
    authorization: enabled

开启安全模式之后,可以连接MongoDB,但是无法操作数据库。

5.1.4 通过用户密码连接MongoDB

mongo -u admin -p

5.2 其他认证方式

MongoDB还支持x.509、Kerberos 身份验证、LDAP 代理验证、内部/会员身份验证

5.3 集合级访问控制

官方文档

六 主从复制

七 分片

八 MongoDB Compass(可视化工具)

8.1 下载

从官网下载。
MongoDB学习笔记_第11张图片

8.2 连接

MongoDB学习笔记_第12张图片
MongoDB学习笔记_第13张图片

九 集成springboot

  1. 添加依赖

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-mongodbartifactId>
    dependency>
    
  2. 配置数据源

    spring:
      data:
        mongodb:
    #      host: 192.168.10.128
    #      port: 27017
    #      username: admin
    #      password: admin
    #      database: test
          uri: mongodb://root:[email protected]:27017/test?authSource=admin&readPreference=primary&serverSelectionTimeoutMS=2000&appname=MongoDB%20Compass&directConnection=true&ssl=false
    
  3. 注入 MongoTemplate

    @Autowired
    private MongoTemplate mongoTemplate;
    
  4. 使用

    import com.guoli.mongodbstudy.pojo.Student;
    import com.mongodb.client.result.DeleteResult;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Sort;
    import org.springframework.data.mongodb.core.MongoTemplate;
    import org.springframework.data.mongodb.core.query.Criteria;
    import org.springframework.data.mongodb.core.query.Query;
    
    import java.util.List;
    
    @SpringBootTest
    class MongodbStudyApplicationTests {
        @Autowired
        private MongoTemplate mongoTemplate;
    
        @Test
        void insert() {
    //        mongoTemplate.insert("{\"name\": \"zs\", \"age\": 18, \"source\": 80.6}", "student");
            for (int i = 0; i < 9; i++) {
                Student s = mongoTemplate.insert(new Student(i, "ls" + i, 20 + i, 90.5 + i));
                System.out.println(s);
            }
        }
    
        @Test
        void findAll() {
            List<Student> students = mongoTemplate.findAll(Student.class);
            students.forEach(System.out::println);
        }
    
        @Test
        void findById() {
            Student student = mongoTemplate.findById(1, Student.class);
            System.out.println(student);
        }
    
        @Test
        void find() {
            Query query = new Query();
            // 指定返回结果包含的字段
    //        query.fields().include("name");
            // 指定返回结果不包含的字段
    //        query.fields().exclude("name");
            // 根据字段查找
    //        query.addCriteria(new Criteria().and("age").is(21));
    //        query.addCriteria(new Criteria().and("name").regex("l.*"));
            query.addCriteria(new Criteria("age").is(21)).addCriteria(new Criteria("name").regex("l.*"));
            // 大于、小于或等于
    //        query.addCriteria(Criteria.where("age").gt(25));
    //        query.addCriteria(Criteria.where("age").lte(25));
            query.collation()
            List<Student> students = mongoTemplate.find(query, Student.class);
            students.forEach(System.out::println);
        }
    
        @Test
        void findSort() {
            Query query = new Query();
            query.with(Sort.by(Sort.Direction.DESC, "age"));
            List<Student> students = mongoTemplate.find(query, Student.class);
            students.forEach(System.out::println);
        }
    
        @Test
        void findPage() {
            Query query = new Query();
            query.with(PageRequest.of(1, 3));
            List<Student> students = mongoTemplate.find(query, Student.class);
            students.forEach(System.out::println);
        }
    
        @Test
        void remove() {
            Query query = new Query();
            DeleteResult deleteResult = mongoTemplate.remove(query, Student.class);
            System.out.println(deleteResult.wasAcknowledged());
            System.out.println(deleteResult.getDeletedCount());
        }
    
        @Test
        void drop() {
            mongoTemplate.dropCollection(Student.class);
        }
    }
    

你可能感兴趣的:(中间件,数据库,数据库,数据结构,mongodb,大数据)