MongoDB基础操作

文章目录

    • 一、什么是MongoDB
    • 二、MongoDB 与关系型数据库对比
    • 三、数据类型
    • 四、部署MongoDB
      • 1、下载二进制包
      • 2、下载安装包并解压
      • 3、创建用于存放数据和日志的目录,并修改权限
      • 4、启动MongoDB
        • 4.1前台启动
        • 4.2后台启动
        • 4.3、配置文件启动服务
        • 4.4、配置systemd服务
        • 4.5、systemctl启动MongoDB
      • 5、客户端配置
      • 6、关闭MongoDB
        • 6.1、前台启动
        • 6.2、后台启动
        • 6.3、kill命令关闭
        • 6.4、MongoDB函数关闭
    • 五、MongoDB基本操作及增删改查
      • 1、基本操作
        • 1.1、登录数据库
        • 1.2、查看数据库
        • 1.3、查看当前正在使用的数据库
        • 1.4、选择/创建数据库
        • 1.5、查看集合
        • 1.6、创建集合
        • 1.7、删除集合
        • 1.8、删除数据库
      • 2、增删改查
        • 2.1、插入文档
          • 2.1.1、一次性插入多条数据
        • 2.2、查询文档
          • 2.2.1、查询集合内所有的记录数
        • 2.3、修改文档
        • 2.4、删除文档
    • 六、MongoDB支持存储的数据类型
      • 1、数字
      • 2、字符串
      • 3、正则表达式
      • 4、数组
      • 5、日期
      • 6、内嵌文档
    • 七、MongoDB中的索引
      • 1、查看索引
      • 2、需要索引的查询场景
        • 2.1、创建有10000个文档的集合
        • 2.2、查询`age`为`200`的文档
        • 2.3、添加`limit`查询文档
        • 2.4、创建索引
        • 2.5、自定义索引名字
      • 3、查看索引的大小
      • 4、删除索引
        • 4.1、按名称删除索引
        • 4.2、删除所有的索引
      • 5、优缺点
        • 5.1、优点:
        • 5.2、缺点:

一、什么是MongoDB

MongoDB 是一个开源、高性能、无模式的、基于分布式文件存储的文档型数据库,当初的设计就是用于简化开发和方便扩展,是 NoSQL 数据库产品中的一种。是最像关系型数据库(MySQL)的非关系型数据库。

它支持的数据结构非常松散,是一种类似于JSON的格式叫BSON(Binary JSON),所以它既可以存储比较复杂的数据类型,又相当的灵活。

二、MongoDB 与关系型数据库对比

webp

SQL 术语/概念MongoDB 术语/概念解释说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
table joins不支持表连接,MongoDB 不支持
不支持嵌入文档MongoDB 通过嵌入式文档来替代多表连接
primary keyprimary key主键,MongoDB 自动将_id 字段设置为主键

三、数据类型

数据类型描述举例
字符串utf8字符串都可以表示为字符串类型的数据{“x”:“foobar”}
对象id对象id是文档的12字节的唯一ID{“X”:Objectid()}
布尔值真或者假:true或者false{“x”:true}
数组值的集合或者列表都可以表示成数组{“x”:[“a”,“b”,“c”]}
整数(Int32 Int64 你们就知道有个Int就行了,一般我们用Int32){“age”:18}
null表示空值或者未定义的对象{“x”:null}
undefined文档中也可以使用未定义类型{“x”:undefined}

四、部署MongoDB

1、下载二进制包

下载地址

image-20240424165506053

2、下载安装包并解压

wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.4.6.tgz
tar xzvf mongodb-linux-x86_64-rhel70-4.4.6.tgz -C /usr/local
cd /usr/local/
ln -s /usr/local/mongodb-linux-x86_64-rhel70-4.4.6 /usr/local/mongodb

3、创建用于存放数据和日志的目录,并修改权限

# 创建存放数据的目录
mkdir -p /usr/local/mongodb/data/db
# 创建存放日志的目录
mkdir -p /usr/local/mongodb/logs
# 创建日志记录文件
touch /usr/local/mongodb/logs/mongodb.log

4、启动MongoDB

4.1前台启动

MongoDB的默认启动方式为前台启动

cd /usr/local/mongodb/bin/mongod \
--dbpath /usr/local/mongodb/data/db/ \
--logpath /usr/local/mongodb/logs/mongodb.log \
--logappend \
--port 27017 \
--bind_ip 0.0.0.0

参数解释:

 --dbpath:指定数据文件存放目录--logpath:指定日志文件,注意是指定文件不是目录--logappend:使用追加的方式记录日志--port:指定端口,默认为 27017--bind_ip:绑定服务 IP,若绑定 127.0.0.1,则只能本机访问,默认为本机地址
4.2后台启动

后台启动在命令中添加–fork即可

cd /usr/local/mongodb/bin/mongod \
--dbpath /usr/local/mongodb/data/db/ \
--logpath /usr/local/mongodb/logs/mongodb.log \
--logappend \
--port 27017 \
--bind_ip 0.0.0.0 \
--fork
4.3、配置文件启动服务

bin目录下增加一个mongodb.conf配置文件

vim /usr/local/mongodb/bin/mongodb.conf
# 数据文件存放目录
dbpath = /usr/local/mongodb/data/db
# 日志文件存放目录
logpath = /usr/local/mongodb/logs/mongodb.log
# 以追加的方式记录日志
logappend = true
# 端口默认为 27017
port = 27017
# 对访问 IP 地址不做限制,默认为本机地址
bind_ip = 0.0.0.0
# 以守护进程的方式启用,即在后台运行
fork = true

image-20240424171746978

启动命令:

bin/mongod -f /usr/local/mongodb/bin/mongodb.conf

image-20240424172044021

4.4、配置systemd服务
vim /usr/lib/systemd/system/mongodb.service[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target 
[Service] 
Type=forking 
ExecStart=/usr/local/mongodb/bin/mongod --config /usr/local/mongodb/bin/mongodb.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/usr/local/mongodb/bin/mongod --shutdown --config /usr/local/mongodb/bin/mongodb.conf
PrivateTmp=true 
[Install] 
WantedBy=multi-user.targetchmod 754 /usr/lib/systemd/system/mongodb.service
4.5、systemctl启动MongoDB
systemctl start mongodb

5、客户端配置

添加环境变量

echo "export PATH=/usr/local/mongodb/bin/:$PATH" >> /etc/profile
source /etc/profile
mongo

6、关闭MongoDB

6.1、前台启动
Ctrl + c
6.2、后台启动
# 命令启动方式的关闭
bin/mongod --dbpath /usr/local/mongodb/data/db/ --logpath /usr/local/mongodb/logs/mongodb.log --logappend --port 27017 --bind_ip 0.0.0.0 --fork --shutdown
# 配置文件启动方式的关闭
bin/mongod -f /usr/local/mongodb/bin/mongodb.conf --shutdown
6.3、kill命令关闭

不推荐使用

# 查看 mongodb 运行的进程信息
ps -ef | grep mongodb
# kill -9 强制关闭
kill -9 pid
6.4、MongoDB函数关闭
# 连接 mongodb
mongo
# 切换 admin 数据库
use admin
# 执行以下函数(2选1)即可关闭服务
db.shutdownServer()
db.runCommand("shutdown")

五、MongoDB基本操作及增删改查

1、基本操作

1.1、登录数据库
mongo
1.2、查看数据库
show databases
show dbs

image-20240424183039764

1.3、查看当前正在使用的数据库
db

image-20240425115609645

1.4、选择/创建数据库
use admin

image-20240425114338328

如果切换到一个没有的数据库,那么会隐式创建这个数据库。(后期当该数据库有数据时,系统自动创建)

use admin1

image-20240425114612080

1.5、查看集合
show collections

image-20240425114752959

1.6、创建集合
db.createCollection('集合名')

image-20240425115030221

1.7、删除集合
db.集合名.drop()

image-20240425115744209

1.8、删除数据库

通过use语法选择数据
通过db.dropDataBase()删除数据库

> use admin1
switched to db admin1
> show collections
c2
> db.dropDatabase()
{ "dropped" : "admin1", "ok" : 1 }
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

image-20240425120604758

2、增删改查

2.1、插入文档

如果集合存在,那么直接插入数据。

如果集合不存在,那么会隐式创建。

db.集合名.insert(JSON数据)
  • 在test1数据库的c1集合中插入文档,(姓名:张三,年龄:18)
> use test1
switched to db test1
> show collections
> db.createCollection('c1')
{ "ok" : 1 }
> db.c1.insert({name:"张三",age:18})
WriteResult({ "nInserted" : 1 })
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "张三", "age" : 18 }

image-20240425125211753

  • 数据库和集合不存在都隐式创建
  • 对象的键统一不加引号(方便看),但是查看集合数据时系统会自动加
  • mongodb会给每条数据增加一个全球唯一的_id
2.1.1、一次性插入多条数据
  • 数组中一个个写入json数据
> db.c1.insert([{name:"李四",age:20},{name:"王五",age:21},{name:"赵六",age:22}])
BulkWriteResult({"writeErrors" : [ ],"writeConcernErrors" : [ ],"nInserted" : 3,"nUpserted" : 0,"nMatched" : 0,"nModified" : 0,"nRemoved" : 0,"upserted" : [ ]
})
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "张三", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "赵六", "age" : 22 }

image-20240425125249398

  • 写for循环插入数据
> for (var i=1;i<=10;i++) {db.c1.insert({name:"a"+i , age: i}) }
WriteResult({ "nInserted" : 1 })
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "张三", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "赵六", "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "name" : "a1", "age" : 1 }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "name" : "a2", "age" : 2 }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "name" : "a3", "age" : 3 }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "name" : "a4", "age" : 4 }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "name" : "a5", "age" : 5 }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "name" : "a6", "age" : 6 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8", "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9", "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425125400607

2.2、查询文档
db.集合名.find(条件[,查询的列])
条件写法
查询所有的数据{}或者不写
查询age=6的数据{age:6}
既要age=6又要性别=男{age:6,sex:‘男’}
查询的列(可选参数)写法
查询全部列(字段)不写
只显示age列(字段){age:1}
除了age列(字段)都显示{age:0}

其他语法

db.集合名.find({键:{运算符:值}})
运算符作用
$gt大于
$gte大于等于
$lt小于
$lte小于等于
$ne不等于
$inin
$ninnot in
  • 查看所有数据
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "张三", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "赵六", "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "name" : "a1", "age" : 1 }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "name" : "a2", "age" : 2 }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "name" : "a3", "age" : 3 }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "name" : "a4", "age" : 4 }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "name" : "a5", "age" : 5 }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "name" : "a6", "age" : 6 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8", "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9", "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425125449664

  • 只看name列
> db.c1.find({},{name:1})
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "张三" }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四" }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五" }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "赵六" }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "name" : "a1" }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "name" : "a2" }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "name" : "a3" }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "name" : "a4" }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "name" : "a5" }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "name" : "a6" }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7" }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8" }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9" }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10" }

image-20240425125526995

  • 查看除了name列
> db.c1.find({},{name:0})
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "age" : 1 }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "age" : 2 }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "age" : 3 }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "age" : 4 }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "age" : 5 }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "age" : 6 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "age" : 10 }

image-20240425125554132

  • 查询age大于6的数据
> db.c1.find({age:{$gt:6}})
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "张三", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "赵六", "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8", "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9", "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425125634325

  • 查询年龄为7岁、10岁、18岁的数据
> db.c1.find({age:{$in:[7,10,18]}})
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "张三", "age" : 18 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425142853007

2.2.1、查询集合内所有的记录数
db.集合名.count()

image-20240425205417337

2.3、修改文档
db.集合名.update(<filter>,          // 查询条件(筛选待更新的文档)<update>,          // 更新操作定义(如何修改文档){upsert: <boolean>,  // 可选,如果无匹配文档则插入,默认为 falsemulti: <boolean>,   // 可选,是否更新所有匹配的文档,默认为 false(仅更新第一条)collation: <object>, // 可选,指定比较选项(如大小写敏感等)arrayFilters: <array>, // 可选,用于处理嵌套数组中的条件匹配hint: <string|document>, // 可选,提供索引来指导查询writeConcern: <document>, // 可选,指定写关注级别let: <object> // 可选,用于与聚合管道更新相关的变量定义}
)
  • {name:"张三"}修改为{name:"zhangsan"}
> db.c1.update({name:"张三"},{$set:{name:"zhangsan"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.c1.find()
{ "_id" : ObjectId("6629dc959117871a1f5ab723"), "name" : "zhangsan", "age" : 18 }
{ "_id" : ObjectId("6629de189117871a1f5ab724"), "name" : "李四", "age" : 20 }
{ "_id" : ObjectId("6629de189117871a1f5ab725"), "name" : "王五", "age" : 21 }
{ "_id" : ObjectId("6629de189117871a1f5ab726"), "name" : "赵六", "age" : 22 }
{ "_id" : ObjectId("6629def99117871a1f5ab727"), "name" : "a1", "age" : 1 }
{ "_id" : ObjectId("6629def99117871a1f5ab728"), "name" : "a2", "age" : 2 }
{ "_id" : ObjectId("6629def99117871a1f5ab729"), "name" : "a3", "age" : 3 }
{ "_id" : ObjectId("6629def99117871a1f5ab72a"), "name" : "a4", "age" : 4 }
{ "_id" : ObjectId("6629def99117871a1f5ab72b"), "name" : "a5", "age" : 5 }
{ "_id" : ObjectId("6629def99117871a1f5ab72c"), "name" : "a6", "age" : 6 }
{ "_id" : ObjectId("6629def99117871a1f5ab72d"), "name" : "a7", "age" : 7 }
{ "_id" : ObjectId("6629def99117871a1f5ab72e"), "name" : "a8", "age" : 8 }
{ "_id" : ObjectId("6629def99117871a1f5ab72f"), "name" : "a9", "age" : 9 }
{ "_id" : ObjectId("6629def99117871a1f5ab730"), "name" : "a10", "age" : 10 }

image-20240425184009386

  • {name:"李四"}的年龄加/减5

年龄加5

db.c1.update({name:"李四"},{$inc:{age:5}})

image-20240425184419154

年龄减5

db.c1.update({name:"李四"},{$inc:{age:-5}})

image-20240425184616300

2.4、删除文档
db.集合名.remove(条件[,是否删除一条])
  • 删除一条数据

    • db.c1.remove({},true)
      

      默认删除的第一条数据

      image-20240425204653851

    • db.c1.remove({name:"李四"})
      

      删除指定数据

      image-20240425204856853

六、MongoDB支持存储的数据类型

1、数字

  • shell默认使用64位浮点型数值
db.b1.insert({x:3.1415926})
db.b1.insert({x:3})

image-20240425213512686

  • 整型值,可以用NumberInt或者NumberLong表示
db.b1.insert({x:NumberInt(10)})
db.b1.insert({x:NumberLong(12)})

image-20240425213843340

2、字符串

db.b1.insert({x:"hello MongoDB!"})

image-20240425214353152

3、正则表达式

查询所有keyx,valuehello开头的文档且不区分大小写

db.b1.find({x:/^(hello).(.[a-zA-Z0-9])+/i})

image-20240425214936289

4、数组

数组中的数据类型可以是多种多样的

db.b1.insert({x:[1,2,3,4,new Date()]})

image-20240425215940415

5、日期

db.b1.insert({x:new Date()})

image-20240425220308105

6、内嵌文档

一个文档也可以作为另一个文档的value

db.b1.insert({name:"三国演义",author:{name:"罗贯中",age:70}})

image-20240425221008151

七、MongoDB中的索引

1、查看索引

默认情况下,集合中的_id字段就是索引,我们可以通过getIndexes()方法来查看一个集合中的索引:

db.b1.getIndexes()

image-20240425222309926

  1. v: 表示索引版本。在这个例子中,值为 2,表示这是一个版本 2 的索引。索引版本通常由 MongoDB 内部管理,用户通常不需要直接关心。
  2. key: 描述了索引的键(即排序依据)。键是一个对象,键名为字段名,键值为排序方向。在给出的例子中,{ "_id" : 1 } 表示索引基于字段 _id,且按升序(1)排序。在 MongoDB 中,每个集合都默认有一个名为 _id 的主键索引,它是唯一的,并且总是按升序排列。
  3. name: 指定索引的名称。这里为 "name" : "_id_",表示这是一个针对 _id 字段的索引,其名称默认为 _id_。在 MongoDB 中,主键索引的名称通常是固定的,即 _id_

2、需要索引的查询场景

2.1、创建有10000个文档的集合
for (var i=1;i<=10000;i++) {db.q1.insert({name:"test"+i , age: i})}
db.q1.count()

image-20240426082844602

2.2、查询age200的文档
db.q1.find({age:200})

image-20240425230647795

这种查询默认情况下会做全表扫描,可以用explain()来查看一下查询计划

db.q1.find({age:200}).explain("executionStats")
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "test3.q1","indexFilterSet" : false,"parsedQuery" : {"age" : {"$eq" : 200}},"winningPlan" : {"stage" : "COLLSCAN","filter" : {"age" : {"$eq" : 200}},"direction" : "forward"},"rejectedPlans" : [ ]},"executionStats" : {"executionSuccess" : true,"nReturned" : 1,"executionTimeMillis" : 2,"totalKeysExamined" : 0,"totalDocsExamined" : 10000,"executionStages" : {"stage" : "COLLSCAN","filter" : {"age" : {"$eq" : 200}},"nReturned" : 1,"executionTimeMillisEstimate" : 0,"works" : 10002,"advanced" : 1,"needTime" : 10000,"needYield" : 0,"saveState" : 10,"restoreState" : 10,"isEOF" : 1,"direction" : "forward","docsExamined" : 10000}},"serverInfo" : {"host" : "localhost.localdomain","port" : 27017,"version" : "4.4.6","gitVersion" : "72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"},"ok" : 1
}

queryPlanner 部分

  • plannerVersion: 表示查询优化器的版本。
  • namespace: 查询涉及的集合名,即 test3.q1
  • indexFilterSet: 若为 true,表示查询使用了索引过滤器;此处为 false,说明没有使用。
  • parsedQuery: 显示解析后的查询条件,即查找 age 字段等于 200 的文档。
  • winningPlan: 描述被选择的执行计划。在这个案例中,执行计划的 stage"COLLSCAN",意味着进行了全集合扫描(Collection Scan)。这意味着为了找到匹配的文档,MongoDB 需要遍历整个 q1 集合,对每个文档应用 filter 中指定的条件(age: { $eq: 200 })。
  • rejectedPlans: 空数组,表示没有其他备选执行计划被否决。如果有多个可行计划,MongoDB 会选择成本最低的一个作为 winningPlan,其余的则记录在此处。

executionStats 部分

这部分提供了实际执行查询时的统计信息:

  • executionSuccess: 指示查询是否成功完成,true 表示成功。
  • nReturned: 返回的文档数量,这里是 1,说明找到了一个年龄为 200 的文档。
  • executionTimeMillis: 执行查询所花费的时间(毫秒),本例中为 2 毫秒。
  • totalKeysExamined: 查看的索引键数量。由于未使用索引,此处为 0
  • totalDocsExamined: 查看的文档数量,即全集合扫描过程中检查过的文档总数,这里为 10000,表明集合中有 10000 个文档被逐一检查以找出符合 age: 200 的文档。
  • executionStages: 提供了更多关于执行阶段的细节,与 winningPlan 相对应。这里再次确认了进行了全集合扫描(COLLSCAN),并且实际查看了 10000 个文档 (docsExamined) 才找到 1 个匹配的文档 (nReturned).

serverInfo 部分

  • 提供了运行 MongoDB 服务器的主机名、端口、版本号以及 Git 版本信息。

ok

  • 值为 1,表示命令执行成功。
2.3、添加limit查询文档
db.q1.find({age:10}).limit(20)db.q1.find({age:10}).limit(20).explain("executionStats")
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "test3.q1","indexFilterSet" : false,"parsedQuery" : {"age" : {"$eq" : 10}},"winningPlan" : {"stage" : "LIMIT","limitAmount" : 20,"inputStage" : {"stage" : "COLLSCAN","filter" : {"age" : {"$eq" : 10}},"direction" : "forward"}},"rejectedPlans" : [ ]},"executionStats" : {"executionSuccess" : true,"nReturned" : 1,"executionTimeMillis" : 4,"totalKeysExamined" : 0,"totalDocsExamined" : 10000,"executionStages" : {"stage" : "LIMIT","nReturned" : 1,"executionTimeMillisEstimate" : 1,"works" : 10002,"advanced" : 1,"needTime" : 10000,"needYield" : 0,"saveState" : 10,"restoreState" : 10,"isEOF" : 1,"limitAmount" : 20,"inputStage" : {"stage" : "COLLSCAN","filter" : {"age" : {"$eq" : 10}},"nReturned" : 1,"executionTimeMillisEstimate" : 1,"works" : 10002,"advanced" : 1,"needTime" : 10000,"needYield" : 0,"saveState" : 10,"restoreState" : 10,"isEOF" : 1,"direction" : "forward","docsExamined" : 10000}}},"serverInfo" : {"host" : "localhost.localdomain","port" : 27017,"version" : "4.4.6","gitVersion" : "72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"},"ok" : 1
}

可以明显感受到加了limit后查询速度变快了很多

但是如果我们查询age9999的文档那么还是得全表扫描一遍

此时我们就可以给该字段加上索引

2.4、创建索引
db.collection.createIndex(keys, options)

参数:

  • keys:

    • 包含字段和值对的文档,其中字段是索引键,描述该字段的索引类型
    • 对于字段的上升索引,请指定为1,对于降序指定为-1
  • options:

    • 可选,包含一组控制索引创建的选项的文档
    选项类型描述
    background布尔是否在后台执行创建索引的过程,不阻塞对集合的操作false【默认】
    unique布尔是否创建具有唯一性的索引 false【默认】
    name字符串自定义索引名称,如果不指定,mongodb将通过 下划线 连接 索引字段的名称和排序规则 生成一个索引名称。一旦创建不能修改,只能删除再重新创建
    partialFilterExpressionDocument仅为集合中符合条件的文档建立索引,降低创建和维护成本
    sparse布尔仅为集合中具有指定字段的文档建立索引 false 【默认】
    expireAfterSecondsinteger单位 秒用于 TTL 索引中 控制 文档保存在集合中的时间
    storageEngineDocument指定存储引擎配置
db.q1.ensureIndex({age:1})

查看查询计划

db.q1.find({age:200}).explain("executionStats")
> db.q1.find({age:200}).explain("executionStats")
{"queryPlanner" : {"plannerVersion" : 1,"namespace" : "test3.q1","indexFilterSet" : false,"parsedQuery" : {"age" : {"$eq" : 200}},"winningPlan" : {"stage" : "FETCH","inputStage" : {"stage" : "IXSCAN","keyPattern" : {"age" : 1},"indexName" : "age_1","isMultiKey" : false,"multiKeyPaths" : {"age" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"age" : ["[200.0, 200.0]"]}}},"rejectedPlans" : [ ]},"executionStats" : {"executionSuccess" : true,"nReturned" : 1,"executionTimeMillis" : 1,"totalKeysExamined" : 1,"totalDocsExamined" : 1,"executionStages" : {"stage" : "FETCH","nReturned" : 1,"executionTimeMillisEstimate" : 0,"works" : 2,"advanced" : 1,"needTime" : 0,"needYield" : 0,"saveState" : 0,"restoreState" : 0,"isEOF" : 1,"docsExamined" : 1,"alreadyHasObj" : 0,"inputStage" : {"stage" : "IXSCAN","nReturned" : 1,"executionTimeMillisEstimate" : 0,"works" : 2,"advanced" : 1,"needTime" : 0,"needYield" : 0,"saveState" : 0,"restoreState" : 0,"isEOF" : 1,"keyPattern" : {"age" : 1},"indexName" : "age_1","isMultiKey" : false,"multiKeyPaths" : {"age" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward","indexBounds" : {"age" : ["[200.0, 200.0]"]},"keysExamined" : 1,"seeks" : 1,"dupsTested" : 0,"dupsDropped" : 0}}},"serverInfo" : {"host" : "localhost.localdomain","port" : 27017,"version" : "4.4.6","gitVersion" : "72e66213c2c3eab37d9358d5e78ad7f5c1d0d0d7"},"ok" : 1
}
  • executionTimeMillis:执行耗时 1 毫秒。

  • totalKeysExaminedtotalDocsExamined:分别检查了 1 个索引键和 1 个文档。由于使用了覆盖索引(即索引包含了查询所需的所有字段),这里的两个值相等,意味着无需额外查询文档。

查看索引

> db.q1.getIndexes()
[{"v" : 2,"key" : {"_id" : 1},"name" : "_id_"},{"v" : 2,"key" : {"age" : 1},"name" : "age_1"}
]

image-20240426093010417

2.5、自定义索引名字
db.q1.ensureIndex({name:1},{name:"MyNameIndex"})

image-20240426102603193

3、查看索引的大小

默认单位是字节

db.q1.totalIndexSize()

image-20240426102044812

4、删除索引

4.1、按名称删除索引
db.q1.dropIndex("MyNameIndex")

image-20240426102841487

4.2、删除所有的索引
db.q1.dropIndexes()

image-20240426103015481

5、优缺点

5.1、优点:
  • **提高查询性能:**索引能够大大加快数据查询速度,特别是对于含有复杂查询条件、排序、分组或聚合操作的查询。
  • 支持高效排序:当查询需要对特定字段进行排序时,如果该字段有索引,MongoDB可以直接利用索引来完成排序,避免了大量数据的内部排序操作,显著提升性能。
  • 覆盖查询:如果一个索引包含了查询所需的全部字段,称为“覆盖索引”。在这种情况下,MongoDB可以直接从索引中获取所有数据,而无需访问实际文档,从而减少磁盘I/O操作,提高查询效率。
  • 唯一性约束:创建唯一索引可以确保指定字段的值在整个集合中唯一,防止插入重复数据,确保数据完整性。
5.2、缺点:
  • 占用存储空间:索引需要额外的存储空间来保存索引数据结构。随着数据量的增长和索引数量的增加,存储开销会逐渐增大。需要根据实际业务需求权衡查询性能与存储成本。
  • 写操作性能影响:插入、更新和删除文档时,不仅要修改原数据,还要同步更新相关索引。对于写密集型应用,大量的索引可能导致写操作性能下降,尤其是当索引较多或索引字段频繁变动时。
  • 索引维护成本:随着数据的变化,索引需要不断维护和更新。对于大型数据集,索引重建可能需要消耗较长时间和系统资源。此外,随着业务发展,可能需要定期评估和调整索引策略,以适应新的查询模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/3940.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ发布确认和消息回退(6)

概念 发布确认原理 生产者将信道设置成 confirm 模式&#xff0c;一旦信道进入 confirm 模式&#xff0c;所有在该信道上面发布的消息都将会被指派一个唯一的 ID(从 1 开始)&#xff0c;一旦消息被投递到所有匹配的队列之后&#xff0c;broker就会发送一个确认给生产者(包含消…

qt实现方框调整

效果 在四周调整 代码 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QWidget>class MainWindow : public QWidget {Q_OBJECT public:explicit MainWindow(QWidget *parent 0);~MainWindow();void paintEvent(QPaintEvent *event);void updateRect();void re…

Restful API 具体设计规范(概述)

协议 https 域名 https://www.baidu.com/api 版本 https://www.baidu.com/v1 路径 https://www.baidu.com/v1/blogs 方法 数据过滤 状态码返回结果 返回的数据格式 尽量使用 JSON&#xff0c;避免使用 XML。 总结&#xff1a; 看 url 就知道要什么看 http method 就知道干…

Linux进阶篇:CentOS7搭建NFS文件共享服务

CentOS7搭建NFS文件共享服务 一、NFS介绍 NFS(Network File System)意为网络文件系统&#xff0c;它最大的功能就是可以通过网络&#xff0c;让不同的机器不同的操作系统可以共享彼此的文件。简单的讲就是可以挂载远程主机的共享目录到本地&#xff0c;就像操作本地磁盘一样&…

Docker——数据管理和网络通信

目录 一、Docker的数据管理 1.数据卷 2.数据卷容器 3.容器互联 二、Docker镜像的创建 1.基于现有镜像创建 2.基于本地模板创建 3.基于Dockerfile 创建 3.1联合文件系统&#xff08;UnionFS&#xff09; 3.2镜像加载原理 3.3为什么Docker里的Centos大小才200M 4.Dcok…

9【PS作图】像素画Tips

放大缩小 “窗口”-排列-为…画布新建窗口&#xff0c;就可以新建一个窗口&#xff0c;实时看作图效果 如果要保持放大或缩小的像素画仍然保持硬边缘&#xff0c;需要设置两个东西 将 编辑 > 首选项 > 常规 中的 插值方式 改为 “邻近&#xff08;靠近硬边缘&#xff09…

HTML网页自动播放背景音乐和全屏背景图代码

HTML网页自动播放背景音乐的代码 背景音乐代码及分析代码的应用背景图代码及分析下期更新预报 背景音乐代码及分析 能使网站上自动循环的背景音乐代码如下&#xff1a; <audio src"music.mid" autostart"true" loop"true" hidden"true…

【小梦C嘎嘎——启航篇】C++四大类型转换

&#x1f60e; 前言&#x1f64c;C四大类型转换什么是类型转换C语言中的类型转换为什么C要嫌弃C语言的类型转换&#xff1f;自行搞一套呢&#xff1f;C强制类型转换1、static_cast2、reinterpret_cast3、const_cast4、dynamic_cast为什么要支持向下转呢&#xff1f; RTTI 总结撒…

RabbitMQ工作模式(4) - 路由模式

概念 路由模式&#xff08;Routing&#xff09;是 RabbitMQ 中的一种消息传递模式&#xff0c;也称为直连模式。它允许生产者将消息发送到一个交换机&#xff0c;并指定一个或多个路由键&#xff08;routing key&#xff09;&#xff0c;交换机根据路由键将消息路由到与之匹配的…

实验7:路由冗余协议HSRP配置管理(课内实验以及解答)

实验目的及要求&#xff1a; 理解首跳冗余协议&#xff08;FHRP&#xff09;的工作原理&#xff0c;掌握热备份路由器协议 (HSRP)&#xff08;思科私有协议&#xff09;原理和配置。能够实现网络终端设备虚拟网关的配置和网络故障的灵活切换&#xff0c;完成相应网络的联通性测…

多模态大语言模型综述

去年以来&#xff0c;我们见证了以 GPT-4V 为代表的多模态大语言模型(Multimodal Large Language Model&#xff0c;MLLM)的飞速发展。为此我们对综述进行了重大升级&#xff0c;帮助大家全面了解该领域的发展现状以及潜在的发展方向。 MLLM 发展脉络图 MLLM 脱胎于近年来广受…

【Redis 开发】缓存雪崩和缓存击穿

缓存问题 缓存雪崩解决方案 缓存击穿互斥锁逻辑时间基于互斥锁解决缓存击穿问题基于逻辑过期方式解决缓存击穿问题 缓存雪崩 缓存雪崩是指在同一时间段&#xff0c;大量的缓存key同时失效或者Redis服务器宕机&#xff0c;导致大量请求到达数据库&#xff0c;带来巨大压力 解决…

Qt | QAbstractButton 抽象类

QAbstractButton 类中的属性 ①、autoExclusive:bool 访问函数:bool autoExclusive() const; void setAutoExclusive(bool); 描述了按钮的自动排他性,若启用了该属性,则属于同一父部件的可选中按钮的行为, 就好像是在同一排他性组中的按钮一样。除了单选按钮,默认为关…

【网络编程】TCP流套接字编程 | Socket类 | ServerSocket类 | 文件资源泄露 | TCP回显服务器 | 网络编程

文章目录 TCP流套接字编程1.ServerSocket类2.Socket类3.文件资源泄露4.**TCP回显服务器** TCP流套接字编程 ​ ServerSocket类和Socket类这两个类都是用来表示socket文件&#xff08;抽象了网卡这样的硬件设备&#xff09;。 TCP是面向字节流的&#xff0c;传输的基本单位是b…

Facebook的未知力量:数字世界的新引擎

在数字化的时代&#xff0c;社交媒体已经成为了我们日常生活中不可或缺的一部分&#xff0c;而Facebook作为其中的巨头&#xff0c;其影响力远远超出了我们的想象。但是&#xff0c;Facebook背后隐藏的力量和影响远不止于此&#xff0c;它正逐渐成为数字世界的新引擎&#xff0…

python 使用flask_httpauth和pyjwt实现登录权限控制

最近需要用到&#xff0c;学习了一下记录 首先安装依赖 pip install Flask-HTTPAuth pyjwt passlib Welcome to Flask-HTTPAuth’s documentation! — Flask-HTTPAuth documentation Welcome to PyJWT — PyJWT 2.8.0 documentation Passlib 1.7.4 documentation — Passl…

Unreal Engine子类化系统UButton

UE系统Button点击事件无法传递参数&#xff0c;通过子类化系统Button添加自定义参数扩展实现Button点击事件参数传递点击C类文件夹&#xff0c;在右边的区域点击鼠标右键&#xff0c;在弹出的菜单中选择“新建C类”在弹出的菜单中选中“显示所有类”&#xff0c;选择Button作为…

Docker从无到有

主要为windows下docker的安装与使用~ 初始Docker Docker理解 对于docker的加简介&#xff0c;我们可以官网获取它的概念&#xff0c;接下来就从什么是docker、为什么要使用docker以及它的作用来进行一个快速入门 前提&#xff1a;项目在发布时&#xff0c;不仅需要其jar包同…

FSMC读取FPGA的FIFO

一、硬件说明 FSMC配置 单片机的代码如下&#xff1a; #define VALUE_ADDRESS_AD1 (__IO uint16_t *)0x60400000while (1){if(!HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_8)) //数据非空{data *(__IO uint16_t *)VALUE_ADDRESS_AD1;data2 *(__IO uint16_t *)VALUE_ADDRESS_AD1…

英伟达助力日本量子技术创新战略!合作打造量子超级计算机 ABCI-Q

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨沛贤 深度好文&#xff1a;1000字丨5分钟阅读 摘要&#xff1a;日本将在英伟达的AI和HPC基础设施的帮助下&#xff0c;通过大规模开发&#xff0c;在量子计算和人工智能领域取…