MongoDB学习笔记

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

在这里插入图片描述

一 安装与卸载

在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++) + "> ";
}

在这里插入图片描述

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

mongo连接后执行

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

在这里插入图片描述

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

mongo连接后执行

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

在这里插入图片描述

2.3 使用外部编译器

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

    export EDITOR=vim
    mongosh
    
  2. 定义函数

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

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

    myFunction
    

    在这里插入图片描述

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

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

DBQuery.shellBatchSize = 3;

在这里插入图片描述

2.5 帮助命令

  • 连接前

    mongosh -h
    mongosh --help
    

    在这里插入图片描述

  • 连接后
    在后面追加上help()方法
    在这里插入图片描述

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 查询

官方文档

在这里插入图片描述

在这里插入图片描述

查询内容输出格式化使用 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>,  # 查询条件,根据查询条件找出要修改的文档,传{}空表示更新第一个文档
       <update>,  # 更新操作
       {
         upsert: <boolean>,  # 默认false,true是当没有匹配的文档是创建一个新的
         writeConcern: <document>,  # 写策略
         collation: <document>,  # 索引语音规则
         arrayFilters: [ <filterdocument1>, ... ],  # 过滤文档数组,用于确定更新操作要修改的数组中的具体元素
         hint:  <document|string>  # 指定查询希望使用的索引字段,如果索引不存在会报错
         multi: <boolean>  # 默认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>,  # 查询条件,根据查询条件找出要替换的文档,传{}空表示替换第一个文档
       <replacement>,  # 替换的文档
       {
         upsert: <boolean>,  # 默认false,true是当没有匹配的文档是创建一个新的
         writeConcern: <document>,  # 写策略
         collation: <document>,  # 索引语音规则
         hint: <document|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(
       <query>,
       {
         justOne: <boolean>,
         writeConcern: <document>,
         collation: <document>,
         let: <document> // Added in MongoDB 5.0
       }
    )
    
  5. 排序后删除并返回第一个

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

    db.collection.findAndModify({
        query: <document>,
        sort: <document>,
        remove: <boolean>,
        update: <document or aggregation pipeline>, // Changed in MongoDB 4.2
        new: <boolean>,
        fields: <document>,
        upsert: <boolean>,
        bypassDocumentValidation: <boolean>,
        writeConcern: <document>,
        collation: <document>,
        arrayFilters: [ <filterdocument1>, ... ],
        let: <document> // 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 下载

官网下载。
下载compass

8.2 连接

在这里插入图片描述
在这里插入图片描述

九 集成springboot

  1. 添加依赖

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

    spring:
      data:
        mongodb:
    #      host: 192.168.10.128
    #      port: 27017
    #      username: admin
    #      password: admin
    #      database: test
          uri: mongodb://root:root@192.168.10.128: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);
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值