• NoSQL数据库之MongoDB


    一、NoSQL数据库背景

    传统关系型数据库遇到的问题

    2008 年左右,网站 、 论坛、社交网络开始高速发展,传统的关系型数据库在存储及处理数据的时候受到了很大的挑战 ,其中主要体现在以下几点:

    • 难以应付每秒上万次的高并发数据写入 。
    • 查询上亿量级数据的速度极其缓慢 。
    • 分库、分表形成的子库到达一定规模后难以进一步扩展 。
    • 分库、分表的规则可能会因为需求变更而发生变更。
    • 修改表结构困难 。
      在很多 互联网应用场景下 , 对数据联表的查询需求不是那么强烈 ,也并不需要在数据写入后立刻读取,但对数据的读取和并发写入速度有非常高的要求 。 在这样的情况下 ,非关系型数据库得到高速的发展 。

    NoSQL简介

    NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。

    MongoDB 就是这样一款非关系型的数据库,什么叫非关系型?就是把数据直接放进一个大仓库,不标号、不连线、单纯的堆起来。传统数据库由于受到各种关系的累赘,各种数据形式的束缚,难以处理海量数据以及超高并发的业务场景。

    NoSQL的特点

    • 可弹性扩展
    • BASE 特性
    • 大数据量、高性能
    • 灵活的数据模型
    • 高可用

    NoSQL数据库有哪些种类

    键值数据库

    这类数据库主要是使用数据结构中的键 Key 来查找特定的数据Value。
    优点:在存储时不采用任何模式,因此极易添加数据
    这类数据库具有极高的读写性能,用于处理大量数据的高访问负载比较合适
    键值对数据库适合大量数据的高访问及写入负载场景,例如日志系统。主要代表是 Redis、Flare

    文档型数据库

    这类数据库满足了海量数据的存储和访问需求,同时对字段要求不严格,可以随意增加、删除、修改字段,且不需要预先定义表结构,所以适用于各种网络应用。
    主要代表是 MongoDB、CouchDB

    列存储型数据库

    主要代表是Cassandra 、Hbase
    这类数据库查找速度快,可扩展性强,适合用作分布式文件存储系统。

    图数据库

    主要代表是InfoGrid 、Neo4J
    这类数据库利用“图结构”的相关算法来存储实体之间的关系信息,适合用于构建社交网络和推荐系统的关系图谱。

    NoSQL 与 RDB 该怎么选择

    NoSQL 并不能完全取代关系型数据库,NoSQL 主要被用来处理大量且多元数据的存储及运算问题。在这样的特性差异下,我们该如何选择合适的数据库以解决数据存储与处理问题呢?这里提供以下几点作为判断依据。

    1. 数据模型的关联性要求
    2. 数据库的性能要求
    3. 数据的一致性要求
    4. 数据的可用性要求

    一个项目并非只选择一种数据库,可以将其拆开设计,将需要 RDB 特性的放到 RDB 中管理,而其它数据放到 NoSQL 中管理。数据模型的关联性要求

    二、MongoDB介绍

    什么是MongoDB

    • 官方文档:https://www.mongodb.com/
    • MongoDB 是由 C++ 语言编写的,是一个基于分布式文件存储的开源 NoSQL 数据库系统。
    • MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
      • 这会让曾经使用过关系型数据库的人比较容易上手
    • MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
    • MongoDB 的查询功能非常强大
      • 不仅支持大部分关系型数据库中的单表查询,还支持范围查询、排序、聚合、MapReduce 等
      • MongoDB 的查询语法类似于面相对象的程序语言

    MongoDB 有哪些特点

    • 文档型数据库
    • 高性能
    • 灵活性
    • 可扩展性
    • 强大的查询语言
    • 优异的性能
    • 高性能:支持使用嵌入数据时,减少系统I/O负担,支持子文档查询
    • 多种查询类型支持,且支持数据聚合查询、文本检索、地址位置查询
    • 高可用、水平扩展:支持副本集与分片
    • 多种存储引擎:WiredTiger , In-Memory

    MongoDB 适用于哪些场景

    1. 需要处理大量的低价值数据,且对数据处理性能有较高要求

    比如,对微博数据的处理就不需要太高的事务性,但是对数据的存取性能有很高的要求,这时就非常适合使用 MongoDB。

    1. 需要借助缓存层来处理数据

    因为 MongoDB 能高效的处理数据,所以非常适合作为缓存层来使用。将 MongoDB 作为持久化缓存层,可以避免底层存储的资源过载。

    1. 需要高度的伸缩性

    对关系型数据库而言,当表的大小达到一定数量级后,其性能会急剧下降。这时可以使用多台 MongoDB 服务器搭建一个集群环境,实现最大程度的扩展,且不影响性能。

    MongoDB安装

    三、MongoDB管理工具介绍

    启动和停止 MongoDB 数据库服务

    mongod --dbpath="C:\mongodb"
    # mongod 默认监听 127.0.0.1:27017。
    
    • 1
    • 2

    管理 MongoDB 服务

    win+R,然后输入 services.msc 打开。
    启动、停止、暂停、恢复、重新启动
    在这里插入图片描述

    mongo Shell

    mongo Shell 是 MongoDB 官方提供的一个在命令行中用来连接操作 MongoDB 服务的客户端工具.使用 mongo Shell 可以对 MongoDB 数据库进行数据的管理

    下载 mongo Shell

    mongo Shell 执行环境

    • 提供了 JavaScript 执行环境
    • 内置了一些数据库操作命令
      • show dbs
      • db
      • use database
      • show collections
    • 提供了一大堆的内置 API 用来操作数据库
      • db.users.insert({ name: ‘Jack’, age: 18 })

    启动 mongo Shell 并连接到 MongoDB

    连接默认端口上的本地 MongoDB 服务

    您可以在没有任何命令行选项的情况下运行 mongo shell,以使用默认端口 27017 连接到在本地主机上运行的 MongoDB 实例:

    mongosh
    
    • 1
    连接非默认端口上的本地 MongoDB 服务

    要明确指定端口,请包括 --port 命令行选项。例如,要使用非默认端口 28015 连接到在 localhost 上运行的 MongoDB 实例,请执行以下操作:

    mongosh --port 28015
    
    • 1
    连接远程主机上的 MongoDB 服务

    连接远程主机上的 MongoDB 服务需要明确指定主机名和端口号。
    您可以指定一个连接字符串。例如,要连接到在远程主机上运行的 MongoDB 实例,请执行以下操作:

    mongo "mongodb://mongodb0.example.com:28015"
    
    • 1

    您可以使用命令行选项 --host <主机>:<端口>。例如,要连接到在远程主机上运行的 MongoDB 实例,请执行以下操作:

    mongosh --host mongodb0.example.com:28015
    
    • 1

    您可以使用–host 和–port 命令行选项。例如,要连接到在远程主机上运行的MongoDB实例,请执行以下操作:

    mongosh --host mongodb0.example.com --port 28015
    
    • 1
    连接具有身份认证的 MongoDB 服务

    您可以在连接字符串中指定用户名,身份验证数据库以及可选的密码。例如,以alice用户身份连接并认证到远程MongoDB实例:

    mongosh "mongodb://alice@mongodb0.examples.com:28015/?authSource=admin"
    
    • 1

    您可以使用–username 和–password,–authenticationDatabase 命令行选项。例如,以alice用户身份连接并认证到远程MongoDB实例:

    mongosh  --username alice --password --authenticationDatabase admin --host mongodb0.examples.com --port 28015
    
    • 1

    注意:如果您指定–password而不输入用户密码,则外壳程序将提示您输入密码。

    退出连接的三种方式
    • exit
    • quit()
    • Ctrl + C

    四、MongoDB

    数据存储结构

    由于 MongoDB 是文档型数据库,其中存储的数据就是熟悉的 JSON 格式数据。

    • 你可以把 MongoDB 数据库想象为一个超级大对象
    • 首先要有数据库Database,比如下面的“京东”
    • 然后要有集合Collection,比如用户、商品
    • 再就是文档Document,比如用户下的张三、李四
    {
      // 数据库 Database
      "京东": {
        // 集合 Collection,对应关系型数据库中的 Table
        "用户": [
          // 文档 Document,对应关系型数据库中的 Row
          {
            // 数据字段 Field,对应关系数据库中的 Column
            "id": 1,
            "username": "张三",
            "password": "123"
          },
          {
            "id": 2,
            "username": "李四",
            "password": "456"
          }
          // ...
        ],
        "商品": [
          {
            "id": 1,
            "name": "iPhone Pro Max",
            "price": 100
          },
          {
            "id": 2,
            "name": "iPad Pro",
            "price": 80
          }
        ],
        "订单": []
        // ...
      },
    
      // 数据库
      "淘宝": {}
    
      // ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    常规操作

    • 查看数据库列表
    show dbs
    
    • 1
    • 查看当前数据库
    db
    
    • 1
    • 创建/切换数据库
    use <DATABASE_NAME>
    
    • 1
    • 数据库名称规则
      • 使用 use 命令切换到要删除的数据库
      • 使用 db.dropDatabase() 删除当前数据库

    集合

    集合类似于关系数据库中的表,MongoDB 将文档存储在集合中。

    • 创建集合
    db.myNewCollection2.insert( { x: 1 } )
    
    • 1
    • 查看集合
    show collections
    
    • 1
    • 删除集合
    db.集合名称.drop()
    
    • 1
    • 创建集合
    show dbs
    
    • 1
    • 创建集合
    show dbs
    
    • 1

    集合名称规则

    集合名称应以下划线或字母字符开头,并且:

    • 不能包含 $
    • 不能为空字符串
    • 不能包含空字符
    • 不能以 . 开头
    • 长度限制
      • 版本 4.2 最大 120 个字节
      • 版本 4.4 最大 255 个字节

    文档

    • MongoDB 将数据记录存储为 BSON 文档
    • BSON(Binary JSON)是 JSON 文档的二进制表示形式,它比 JSON 包含更多的数据类型
    • BSON 规范
    • BSON 支持的数据类型
      在这里插入图片描述

    字段名称

    文档对字段名称有以下限制:

    • 字段名称 _id 保留用作主键;它的值在集合中必须是唯一的,不可变的,并且可以是数组以外的任何类型。
    • 字段名称不能包含空字符。
    • 顶级字段名称不能以美元符号 $ 开头。
      • 从 MongoDB 3.6 开始,服务器允许存储包含点 . 和美元符号 $ 的字段名称

    MongoDB 中的数据类型

    字段的值可以是任何 BSON 数据类型,包括其他文档,数组和文档数组。例如,以下文档包含各种类型的值:
    在这里插入图片描述

    _id 字段

    在 MongoDB 中,存储在集合中的每个文档都需要一个唯一的 _id 字段作为主键。如果插入的文档省略 _id 字段,则 MongoDB 驱动程序会自动为 _id 字段生成 ObjectId。
    _id 字段具有以下行为和约束:

    • 默认情况下,MongoDB 在创建集合时会在 _id 字段上创建唯一索引。
    • _id 字段始终是文档中的第一个字段
    • _id 字段可以包含任何 BSON 数据类型的值,而不是数组。

    基础操作

    在掌握了 MongoDB 中的基础概念之后,下面我们开始学习数据的增删改查,简称 CRUD。

    • Create 创建
    db.inventory.find()
    
    //插入单个
    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" } }
    ])
    
    
    //插入单个 建议用insertOne(它会返回id)
    db.inventory.insert(
      { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
    )
    
    //插入多个 建议用insertMany(它会返回id)
    db.inventory.insert(
    [
      { item: "canvas111", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } },
    	    { item: "canvas222", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }
    ]
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • Read 读取
    db.inventory.insertMany([
      { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
      { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
      { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
      { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
      { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
    ]);
    
    // 第二个参数是查询条件 1表示查询 0表示不查询
    db.inventory.find({},{item:0})
    
    // 查询status为A的数据
    db.inventory.find({status:'A'})
    
    // 查询与 : status为A & qty为45的数据
    db.inventory.find({status:'A',qty:45})
    
    // 查询或 : status为A 或 qty为45的数据
    db.inventory.find({
    	$or:[
    	{status:'A'},
    	{qty:45}
    	]
    })
    
    
    // 查询status为A且qty小于30或item是p开头的数据
    db.inventory.find({
     status: "A",
     $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
    })
    
    // 查询大于等于50的数据
    db.inventory.find( { qty: { $gte: 50 } })
    
    // 查询嵌套文档 字段顺序和字段数都要与数据库中的一致
    db.inventory.find({
     size: { h: 14, w: 21, uom: "cm" }
    })
    
    // 查询size 字段中的 uom 字段等于 "in"  的所有文档
    db.inventory.find({
     "size.uom": "in"
    })
    
    // 查询size 字段中的 w 字段小于12的所有文档
    db.inventory.find({
    	"size.w":{$lt:12}
    })
    
    // 查询选择嵌套字段 h 小于 15,嵌套字段 uom 等于 "in",状态字段等于 "D" 的所有文档
    db.inventory.find({
     "size.h": { $lt: 15 },
     "size.uom": "in",
     status: "D"
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    db.inventory.drop()
    db.inventory.find()
    db.inventory.insertMany([
      { item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] },
      { item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] },
      { item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] },
      { item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] },
      { item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] }
    ]);
    
    // 匹配一个数组
    //要在数组上指定相等条件,请使用查询文档 {<field>: <value>},其中 <value> 是要匹配的精确数组,包括元素的顺序。
    //下面的示例查询所有文档,其中字段标签值是按指定顺序恰好具有两个元素 "red""blank" 的数组
    db.inventory.find({
    	tags:["red","blan"]
    })
    
    //不考虑顺序或该数组中的其他元素,请使用 $all 运算符:
    db.inventory.find({
     tags: { $all: ["red", "blank"] }
    })
    
    
    // 查询数组中的元素
    // 以下示例查询所有文档,其中 tag 是一个包含字符串 "red" 作为其元素之一的数组:
    db.inventory.find({
     tags: "red"
    })
    
    // 为数组元素指定多个条件
    // 使用数组元素上的复合过滤条件查询数组
    // 个元素可以满足大于 15 的条件,而另一个元素可以满足小于 20 的条件;或者单个元素可以满足以下两个条件
    db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
    
    // 查询满足多个条件的数组元素
    // 以下示例查询在 dim_cm 数组中包含至少一个同时 大于22  和 小于30 的元素的文档
    db.inventory.find({
     dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } }
    })
    
    // 通过数组索引位置查询元素
    // 下面的示例查询数组 dim_cm 中第二个元素大于 25 的所有文档
    db.inventory.find( { "dim_cm.1": { $gt: 25 } } )
    
    // 通过数组长度查询数组
    // 使用 $size 运算符可按元素数量查询数组。
    //例如,以下选择数组标签具有3个元素的文档。
    db.inventory.find( { "tags": { $size: 3 } } )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    
    db.inventory.drop()
    
    db.inventory.insertMany( [
    { item: "journal", instock: [ { warehouse: "A", qty: 5 }, { warehouse: "C", qty: 15 } ] },
    { item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] },
    { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] },
    { item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] },
    { item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
    ]);
    
    //查询嵌套在数组中的文档
    //以下示例选择库存数组中的元素与指定文档匹配的所有文档:
    db.inventory.find({
    "instock": { warehouse: "A", qty: 5 }
    })
    
    //整个嵌入式/嵌套文档上的相等匹配要求与指定文档(包括字段顺序)完全匹配。例如,以下查询与库存收集中的任何文档都不匹配:
    
    db.inventory.find({
    "instock": { qty: 5, warehouse: "A" }
    })
    
    //在文档数组中的字段上指定查询条件
    //下面的示例选择所有库存数组中包含至少一个嵌入式文档的嵌入式文档,这些嵌入式文档包含值小于或等于20的字段qty
    db.inventory.find( { 'instock.qty': { $lte: 20 } } )
    
    // 使用数组索引在嵌入式文档中查询字段
    // 下面的示例选择所有库存文件,其中库存数组的第一个元素是包含值小于或等于20的字段qty的文档: 
    db.inventory.find( { 'instock.0.qty': { $lte: 20 } } )
    
    // 为文档数组指定多个条件
    // 下面的示例查询库存数组中至少有一个嵌入式文档的文档,这些文档同时包含等于5的字段qty和等于A的字段仓库:
    db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } )
    
    // 下面的示例查询库存数组中至少有一个嵌入式文档的嵌入式文档包含的字段qty大于10且小于或等于20:
    db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } )
    
    // 元素组合满足标准
    //例如,以下查询匹配文档,其中嵌套在库存数组中的任何文档的qty字段都大于10,而数组中的任何文档(但不一定是同一嵌入式文档)的qty字段小于或等于20:
    db.inventory.find( { "instock.qty": { $gt: 10,  $lte: 20 } } )
    
    //下面的示例查询库存数组中具有至少一个包含数量等于5的嵌入式文档和至少一个包含等于A的字段仓库的嵌入式文档(但不一定是同一嵌入式文档)的文档:
    db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    // 指定从查询返回的项目字段
    
    db.inventory.drop()
    
    db.inventory.insertMany( [
     { item: "journal", status: "A", size: { h: 14, w: 21, uom: "cm" }, instock: [ { warehouse: "A", qty: 5 } ] },
     { item: "notebook", status: "A",  size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "C", qty: 5 } ] },
     { item: "paper", status: "D", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "A", qty: 60 } ] },
     { item: "planner", status: "D", size: { h: 22.85, w: 30, uom: "cm" }, instock: [ { warehouse: "A", qty: 40 } ] },
     { item: "postcard", status: "A", size: { h: 10, w: 15.25, uom: "cm" }, instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
    ]);
    
    // 返回匹配文档中所有字段
    // 下面的示例返回状态为 "A" 的清单集合中所有文档的所有字段:
    db.inventory.find( { status: "A" })
    
    // 仅返回指定字段和 _id 字段
    // 通过将投影文档中的 <field> 设置为 1,投影可以显式包含多个字段。以下操作返回与查询匹配的所有文档。在结果集中,在匹配的文档中仅返回项目,状态和默认情况下的 _id 字段。
    db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
    
    // 禁止 _id 字段
    db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
    
    // 0排除的字段
    db.inventory.find( { status: "A" }, { status: 0, instock: 0 } )
    
    //返回嵌入式文档中的特定字段
    db.inventory.find(
       { status: "A" },
       { item: 1, status: 1, "size.uom": 1 }
    )
    
    // 禁止嵌入文档中的特定字段
    db.inventory.find(
       { status: "A" },
       { "size.uom": 0 }
    )
    
    //在数组中的嵌入式文档上投射
    db.inventory.find( { status: "A" }, { item: 1, status: 1, "instock.qty": 1 } )
    
    //返回数组中的项目特定数组元素
    db.inventory.find( { status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } } )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    //查询空字段或缺少字段
    db.inventory.drop()
    
    //查询空字段或缺少字段
    db.inventory.insertMany([
       { _id: 1, item: null },
       { _id: 2 }
    ])
    
    //相等过滤器
    db.inventory.find( { item: null } )
    
    //类型检查
    db.inventory.find( { item : { $type: 10 } } )
    
    //存在检查
    db.inventory.find( { item : { $exists: false } } )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • Update 更新
    
    //更新文档
    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" }
    ] );
    
    
    //更新单个文档
    db.inventory.updateOne(
        { item: "paper" },
        {
          $set: { "size.uom": "cm", status: "P" },
          $currentDate: { lastModified: true }
        }
     )
     
     
     //更新多个文档
     db.inventory.updateMany(
        { "qty": { $lt: 50 } },
        {
          $set: { "size.uom": "in", status: "P" },
          $currentDate: { lastModified: true }
        }
     )
     
     //替换文档
     db.inventory.replaceOne(
        { item: "paper" },
        { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }
     )
     
     
     db.inventory.find()
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • Delete 删除
    //删除文档
    db.inventory.drop()
    
    db.inventory.insertMany( [
       { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
       { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "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" },
    ] );
    
    //删除所有文档
    db.inventory.deleteMany({})
    
    //删除所有符合条件的文档
    db.inventory.deleteMany({ status : "A" })
    
    //仅删除1个符合条件的文档
    db.inventory.deleteOne( { status: "D" } )
    db.inventory.find()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    为了更好的学习 CRUD 及之后的语法,建议选择一款图形软件更方便操作。

    • Robo 3T
    • Studio 3T
    • Navicat
    • MongoDB Compass
      这些工具各有优劣,根据个人喜好选择即可,我这里推荐 Navicat 这个工具。官网
      在这里插入图片描述
  • 相关阅读:
    2022年全国最新消防设施操作员(高级消防设施操作员)真题题库及答案
    计算机网络
    HTML5:七天学会基础动画网页6
    【mysql 高级】索引介绍,索引结构 ,哪些情况下需要创建索引 ,哪些情况下不需要创建索引
    喜获殊荣!迅镭激光获评“2023年苏州市质量奖”!
    Java记录1:Sublime Text写HelloWrold的常见报错
    numpy中计算相关系数的np.corrcoef
    机器学习简介
    React是什么,怎么用
    简单分组汇总
  • 原文地址:https://blog.csdn.net/qq_42308316/article/details/128073184