MongoDB基础操作

server/2024/9/20 7:27:42/ 标签: mongodb, nosql, 运维

文章目录

    • 一、什么是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 , 一般我们用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.ppmy.cn/server/25004.html

相关文章

uniapp 使用地图

可以使用 map | uni-app官网 uniapp中的map标签&#xff0c;也可以自己引入地图的js 如下图 使用 uniapp中的map标签 需要注意要配置key

每天五分钟计算机视觉:基于YOLO算法精确分类定位图片中的对象

滑动窗口的卷积的问题 滑动窗口的卷积实现效率很高,但是它依然不能够输出最精准的边界框,比如下面所示: 我们可以看到蓝色框不论在什么位置都不能很好的确定车的位置,有一个算法是YOLO 算法它能够帮助我们解决这个问题。 YOLO 算法 比如我们的输入图像是100*100,我们会…

煤矿综合自动化智能监控系统

系统概述 建设煤矿井上下工业环网、工业数据集成平台、排水、供电、运输、通风、压风、瓦斯抽放、采掘、智能洗煤厂等智能自动化控制系统&#xff0c;利用多种软硬件接口(OPC协议、驱动通讯、数据库、文本文件、DDE/NETDDE、子网等)&#xff0c;构建全矿井统一、稳定、高效的数…

spring cache(一)介绍

一、介绍 1、背景 项目中使用最多的缓存技术就是Redis,用Redis就可以实现了&#xff0c;为什么需要使用spring cache&#xff1f; 先看下我们使用缓存步骤: &#xff08;1&#xff09;查寻缓存中是否存在数据&#xff0c;如果存在则直接返回结果 &#xff08;2&#xff09…

动态规划:0/1背包问题

01背包问题是一个经典的动态规划问题&#xff0c;它询问在给定的物品和背包容量下&#xff0c;如何选择物品使得背包中的物品总价值最大&#xff0c;同时保证不超过背包的容量限制。物品不能分割&#xff0c;每个物品只能选择放入或不放入背包。 问题定义 输入&#xff1a; 物…

HarmonyOS-Next开源三方库 MPChart:打造出色的图表体验

点击下载源码https://download.csdn.net/download/liuhaikang/89228765 简介 随着移动应用的不断发展&#xff0c;数据可视化成为提高用户体验和数据交流的重要手段之一。在 OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;应用开发中&#xff0c;一个强大而…

大语言模型在专业领域的应用——医疗场景下的大语言模型

大语言模型在专业领域的应用——医疗场景下的大语言模型 构建面向医疗的大语言模型数据资源总结医疗是与人类生活密切相关的重要领域之一。由于具有较强的通用任务解决能力,大语言模型被广泛用于辅助医生处理各种相关医疗任务,例如医疗诊断、临床报告生成、医学语言翻译、心理…

编译工具各版本与操作系统版本号兼容性冷知识 : JetBrains IntelliJ IDEA 各个主要版本及其对应的操作系统版本号的兼容情况

编译工具各版本与操作系统版本号兼容性冷知识 &#x1f9e0;: JetBrains IntelliJ IDEA 各个主要版本及其对应的操作系统版本号的兼容情况 文章目录 编译工具各版本与操作系统版本号兼容性冷知识 &#x1f9e0;: JetBrains IntelliJ IDEA 各个主要版本及其对应的操作系统版本号…

站群SEO优化策略及其遭遇DDoS攻击时的应对方法

一、站群SEO优化策略 站群优化主要是指通过合理布局和内容优化提升一系列网站在搜索引擎中的整体排名表现。以下是一些关键步骤与相关代码示例&#xff08;以WordPress为例&#xff09;&#xff1a; 差异化内容建设&#xff1a; 每个站点的内容必须具有独立性和价值性&#x…

asyncio异步编程(三)

1.异步迭代器 迭代器&#xff1a;内部实现__iter__()和__next__()方法的对象。 可迭代对象&#xff1a;内部实现__iter__()方法&#xff0c;并且可以返回迭代器的对象。 异步迭代器&#xff1a;实现__aiter__()和__anext__()方法的对象。 异步可迭代对象&#xff1a;内部实…

未来已来:深入探索LLAMA3驱动的人工智能革命

大家好&#xff01;相信大家对于AI&#xff08;人工智能&#xff09;的发展已经有了一定的了解&#xff0c;但你是否意识到&#xff0c;到了2024年&#xff0c;AI已经变得如此强大和普及&#xff0c;带来了我们从未想象过的便利和创新呢&#xff1f;让我们一起来看看AI在这个时…

http基础了解

超文本传输协议&#xff08;HTTP&#xff09;是一个用于传输超媒体文档&#xff08;例如 HTML&#xff09;的应用层协议。它是为 Web 浏览器与 Web 服务器之间的通信而设计的&#xff0c;但也可以用于其他目的。HTTP 遵循经典的客户端—服务端模型&#xff0c;客户端打开一个连…

pytorch-解决过拟合之动量与学习率衰减

目录 1. momentum动量2. pytorch增加momentum3. 学习率衰减4. 学习率衰减的方式4.1 loss连续几次无改善衰减 4.2 步进式衰减 1. momentum动量 下图给出了梯度公式和增加了动量的梯度公式&#xff0c;β z k z^k zk其中的 z k z^k zk就是上次的梯度&#xff0c;而β决定了 w k …

【React】反向代理和修改打包后的目录

反向代理 前提是做了反向代理&#xff1a; 安装 http-proxy-middleware npm i http-proxy-middleware在src/下新建 setupProxy.js const proxy require("http-proxy-middleware");module.exports function(app) {app.use(proxy("/api", {target: &qu…

Sublime Vim模式配置:q关闭当前标签页

在Sublime安装目录下的->Packages文件夹下新建User文件夹创建文件Vintage.sublime-commands 路径为Sublime安装目录->Packages->User->Vintage.sublime-commands文件内容如下[{"caption": ":w - Save","command": "save"}…

java中的代理模式

静态代理 public interface SmsService {void sent(String message); } class SmsServiceImpl implements SmsService{Overridepublic void sent(String message) {System.out.println("这是发送的信息:"message);} } class SmsServiceProxy implements SmsService{…

边OTG边充电芯片LDR6500

随着科技的飞速发展&#xff0c;智能移动设备已成为我们生活中不可或缺的一部分。而在这些设备的连接与数据传输中&#xff0c;Type-C接口以其高效、便捷的特性逐渐占据了主导地位。OTG&#xff08;On-The-Go&#xff09;技术则进一步扩展了Type-C接口的功能&#xff0c;使得设…

Linux 解压报错

在linux上面解压压缩包&#xff0c;有可能遇到一下问题&#xff0c;现提供正确语句供参考 一、tar命令解压.zip文件 在使用tar命令解压.zip格式文件时&#xff0c;有时会遇到一下异常 gzip: stdin has more than one entry--rest ignored tar: Child returned status 2 ta…

人脸识别系统

一、引言 随着科技的飞速发展,人脸识别技术已经成为现代社会中一个重要的科技应用领域。人脸识别系统,顾名思义,是通过分析人的面部特征进行身份识别的一种技术。近年来,这一技术在公共安全、金融服务、智能门禁、手机解锁等多个领域得到了广泛应用,极大地提升了社会的安…

【NTN 卫星通信】NTN应该使用FDD还是TDD双工模式

1 概述 现在主流的商用地面通信系统一般都支持FDD和TDD两种模式&#xff0c;实用于不同的频段。那么卫星通信也需要有这两种模式吗&#xff1f; 2 NTN 双工模式分析 在考虑TDD模式时&#xff0c;需要设置保护时间&#xff0c;以防止终端同时发射和接收。该保护时间直接取决于终…