首页 > 数据库 >MongoDB基础知识

MongoDB基础知识

时间:2023-10-09 18:33:13浏览次数:41  
标签:name MongoDB 数据库 db 基础知识 文档 id

1. 简介

MongoDB官方文档

菜鸟教程

1、 NoSQL(Not Only SQL),不仅仅是SQL,主要是指非关系型数据库,是对不同与传统的关系型数据库的数据管理系统的统称

2、 NoSQL用于超大规模数据的存储,这些类型的数据存储吧需要固定的模式,无需多余的操作就可以横向扩展

1.2 NoSQL 和 RDBMS的区分

NoSQL RDBMS
代表着不仅仅是SQL 高度组织化结构化数据
没有声明性的查询语句 结构化查询语言(SQL)
没有预定义的模式 数据和关系都存储在单独的表中
键值对存储、列存储、文档存储、图形数据库 数据操作语言、数据定义语言
最终一致性、而非ACID属性 严格的一致性
非结构化和不可预知的数据 基础事务
CAP定理
高性能、高可用、可伸缩性

1.3 NoSQL 数据库四大家族

1.3.1 键值(Key-Value)存储

特点:键值数据库就像传统语言中使用的哈希表。通过Key添加、查询或者删除数据

优点:查询速度快

缺点:数据无结构化,通常只被当作字符串或者二进制数据存储

应用场景:内存缓存、用户信息比如会话、配置信息、购物车等,主要用于处理大量数据的高访问负载

NoSQL代表:Redis Memcached

1.3.2 文档(Document-Qriented) 存储

特点:文档数据库将数据以文档的形式存储,类似JSON,是一系列数据项的集合,每个数据项都有一个名称与对应的值,值既可以是简单的数据类型,如字符串、数字、日期等;也可以是复杂的类型,如有序列表和关联对象

优点:数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构

缺点:查询性能不高,缺乏统一的查询语句

应用场景:日志、Web应用等

NoSQL代表:MongoDB CouchDB

1.3.3 列(Wide Column Store / Column-Family)存储

特点:列存储数据库将数据存储在列族(Column Family)中,将多个列聚合成一个列族,键仍然存在,但是他们的特点是指向多个列。例如:我们有一个Person类,我们通常会一起查询他们的姓名和年龄,而不是薪资,这种情况下,姓名和年龄就会被放入一个列族中,而薪资则在另一个列族中

优点:列存储查找速度快,扩展性强,更容易进行分布式扩展,适用于分布式文件系统,应对分布式存储的海量数据

缺点:查询性能不高,缺乏统一的查询语句

应用场景:日志、分布式文件系统(对象存储)、推荐画像、时空数据、消息/订单等

NoSQL代表:Cassandra HBase

1.3.4 图形(Graph-Oriented)存储

特点:图形数据库允许我们将数据以图的方式存储

优点:图形相关算法、比如最短路径寻址、N度关系查找等

缺点:很多时候需要对整个图做计算才能得到需要的信息,分布式的集群方式不好做,处理超级节点乏力,没有分片存储机制,国内社区不活跃

应用场景:社交网络、推荐系统等,专注于构建关系图谱

NoSQL代表:Neo4j Infinite Graph

1.4 NoSQL的优缺点和适用情况

1.4.1 优点

  • 高可扩展性
  • 没有标准化
  • 分布式计算
  • 有限的查询功能
  • 低成本

1.4.2 缺点

  • 最终一致是不直观的程序
  • 架构的灵活,半结构化数据
  • 没有复杂的关系

1.4.3 适用情况

  • 数据模型比较简单
  • 需要灵活性更强的IT系统
  • 对数据库性能要求较高
  • 不需要高度的数据一致性
  • 对于始定的Key,比较容易映射复杂值的环境

1.5 MongoDB 介绍

MongoDB是为快速开发互联网Web应用而设计的数据库系统

MongoDB的设计目的是极简、灵活、作为Web应用栈的一部分

MongoDB数据模型是面向文档的,所谓文档是一种类似于JSON的结构,简单理解MongoDB这个数据库中存的是各种各样的JSON(BSON)

1.5.1 相关概念

1、 数据库(database)
数据库是一个仓库,在仓库中可以存放文档

2、 集合(collection)=== 表
集合类似于数组,在集合中可以存放文档

3、 文档(document)=== 行
文档是数据库中的最小单位,我们存储和操作的内容都是文档

SQL术语概念 MongoDB术语概念
database(数据库) database(数据库)
table(表) collection(集合)
row(行) document or BSON document(文档)
column(列) field(字段)
index(索引) index(索引)
table joins(表连接) embedded document and linking(嵌入的文档和链接)
指定任意唯一的列或列组合作为主键 在MongoDB中,主键被自动设置为_id字段
aggregation(e.g.group by) 聚合操作

image

1.5.2 支持的数据类型

image

2. MongoDB的启动

查看MongoDB是否安装成功

mongod --version

mongodb默认使用执行 mongod 命令所处的盘符根目录下的 /data/db 作为自己的数据存储目录

2.1 前台启动

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

所谓的前台启动就是MongoDB启动进程后会占用当前的终端窗口,这时候你就需要重新开启一个终端窗口来写你的shell命令

# 切换到MongoDB安装bin目录
cd D:/software/MongoDB/bin

# 前台启动命令
mongod --dbpath D:/software/MongoDB/data/db/ --logpath D:/software/MongoDB/log/mongod.log --logappend --port 27017 --bind_ip 0.0.0.0

# 也可以简写为:
mongod --dbpath D:/software/MongoDB/data/db/ --logpath D:/software/MongoDB/log/mongod.log

--path:指定数据文件存放目录
--logpath:指定日志文件,注意是指定文件而不是目录
--logappend:使用追加的方式记录日志
--port:指定端口,默认是 27017
--bind_ip:绑定服务ip,若绑定127.0.0.1,则只能本机访问,默认是本机访问

# 前台结束服务
Ctrl+C

2.2 后台启动

所谓的后台启动就是以守卫进程的方式启动MongoDB,只需命令中添加 --fork即可

后台启动不会占用当前的命令窗口

目前命令 命令--fork只适用于Linux/Unix

# 后台启动
mongod --dbpath D:/software/MongoDB/data/db/ --logpath D:/software/MongoDB/log/mongod.log --fork

# 结束服务 结尾加 --shutdown 即可
mongod --dbpath D:/software/MongoDB/data/db/ --logpath D:/software/MongoDB/log/mongod.log --fork --shutdown

2.3 配置文件启动

使用命令启动的方式并不适合管理,毕竟每次输入名称都需要考虑各个参数的配置,我们可以通过配置文件来配置启动参数,然后通过指定文件的方式来使用服务,这样再管理MongoDB就比较方便了

2.3.1 配置文件 mongodb.conf

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

# 数据文件存放目录
dbpath=D:/software/MongoDB/data/db/
# 日志文件存放目录
logpath=D:/software/MongoDB/log/mongod.log
# 以追加的方式记录日志
logappend=true
# 端口默认为 27017
port=27017
# 对访问 IP 地址不做限制,默认为本机地址
bind_ip=127.0.0.1
# 以防护的方式启动,即在后台启动; 由于windows 不支持防护方式,所以一般都是采用前台启动的方式;
# 注意如果是前台启动,执行mongod -f mongodb.conf后,需要另外开启一个新的cmd窗口 开启mongo的连接
# fork = true
# 开启身份认证
auth=true

2.3.2 启动MongoDB

# 1. 启动MongoDB
mongod -f mongodb.conf

2.3.3 新开一个命令窗口,连接启动 mongo 数据库

# 1.  启动mongo
mongo

# 2.  查看数据库(注意:此时是查询不到数据库的,必须要 开启身份认证 才可以查到数据)
show dbs

# 3.  开启身份验证
use admin
db.auth("admin","admin")

# 4. 再次查看 数据库就有数据了
show dbs

2.3.4 关闭/结束

mongod -f mongodb.conf --shutdown

2.4 环境变量启动-推荐

2.4.1 配置全局环境变量

配置环境变量的方法如下:

1、 复制安装MongoDB里面的bin目录的路径 例如:D:\software\MongoDB\bin

2、 选择目录:计算进--属性--高级系统设置--环境变量,在系统变量的path里面,将上面的目录路径添加进去

3、 重启电脑

4、 开启服务
方式一:任务管理器--服务,开启MongoDB服务
方式二:进入MongoDB安装目录bin里面,执行命令 net start mongodb

5、 直接打开cmd,输入 mongo 命令,开启连接 mongo数据库
如果想要退出 连接:exit 或者 ctrl+c

2.4.2 开启身份验证

使用配置环境变量的方式默认是没有开启身份验证的,如果想要开启身份验证,可以执行如下操作

# 1. 添加设置 超级管理员
use admin
db.createUser({ 
    "user" : "admin",
    "pwd": "admin",
    "roles" : [{ 
        role: "root", 
        db: "admin"
    }] 
})

# 2. 退出卸载服务 (bin目录)
mongod --remove

# 3. 重新安装需要输入账号密码的服务(注在原安装命令基础上加上--auth即可)
mongod --install --dbpath D:\software\MongoDB\data\db --logpath D:\software\MongoDBlog\mongodb.log --auth


2.4.3 启动服务

# 启动服务
mongo

# 再次查询验证服务
show dbs 
# 默认是看不到数据库的,需要验证 db.auth("admin","admin") 验证通过才可以;

# 或者直接通过命令:mongo 服务器IP地址:端口/数据库 -u 用户名 -p 密码
mongo 127.0.0.1:27017/admin -u admin -p admin


# 关闭服务
db.shutdownServer()

# 退出客户端
exit

3. 相关服务操作命令如下(bin目录下的操作)

# 1. 创建服务:
mongod --install --dbpath D:/software/MongoDB/data/db/ --logpath D:/software/MongoDB/log/mongod.log 

# 2. 删除服务
mongod remove

# 3. 启动服务
net start mongodb

# 4. 关闭服务
net stop mongodb

4. 常用基本命令

# 1. 查看所有相关命令的使用
help 

# 2. 退出当前
mongo shellexit

# 3. 查看所有的数据库,如果数据库里面没有数据,默认不显示
show dbs

# 4. 查看当前数据库所有的集合
show collections

# 5. 查看当前数据库的所有用户
show users

# 6. 查看当前所在的数据库
db

# 7. 跳转/切换 到指定数据库;如果没有指定的数据库,那么默认是新建数据库
use admin

# 8. mongo函数关闭服务器
user admin(必须切换到admin服务器)db.shutdownServer()

# 9. 查看admin数据库中所有用户信息
db.system.users.find()

# 10. 查看所有数据库相关方法
db.help()

# 11. 查看版本号
db.version()

# 12. mongo shell 清屏cls    

5. MongoDB用户与权限管理

5.1 常用权限

权限 说明
read 允许用户读取指定数据库
readWrite 允许用户读写指定数据库
dbAdmin 允许用户在指定数据库中执行管理函数,如索引创建、删除、查看统计或访问system.profile
userAdmin 允许用户向system.user集合写入,可以在指定数据库里创建、删除、管理用户
readAnyDatabase 必须在admin数据库中定义,赋予用户所有数据库的读权限
readWriteAnyDatabase 必须在admin数据库中定义,赋予用户所有数据库的读写权限
dbAdminAnyDatabase 必须在admin数据库中定义,赋予用户所有数据库的adAdmin权限
userAdminAnyDatabase 必须在admin数据库中定义,赋予用户所有数据库的userAdmin权限
root 必须在admin数据库中定义,超级账号,超级权限

5.2 角色种类

超级用户角色:root

数据库用户角色:read、readWrite;

数据库管理角色:dbAdmin、userAdmin;

集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;

备份恢复角色:backup、restore;

所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase

5.3 创建管理用户-管理员

MongoDB有一个用户管理机制,简单描述为 用户管理组,这个组的用户专门为 管理普通用户 而设的,我们称之为 管理员

管理员通常是没有数据库的读写权限,只有操作用户的权限,所以我们只需赋予管理员userAdminAnyDatabase角色即可

管理员账户 必须在admin数据库下创建

用户被创建在哪个数据库下,就只能在哪个数据库登陆,所以我们把所有的用户都创建在amdin数据下,这样我们切换数据库的时候,就不需要频繁的进行登陆了

# 0.  查看所有数据库 
show dbs

# 1. 切换到admin数据库
user admin

# 2. 查看当前数据库中所有的用户信息
db.system.users.find() 
# 或者
show users


# 3. 创建用户
# 	在MongoDB中,我们可以使用  db.creatUser({用户信息})函数创建用户
# 	3.1 创建用户语法:    
db.create({
	user: "<name>",   # 用户名
	pwd: "<cleartext password>",  # 密码
	#  存放用户相关的自定义数据,可选属性
	customData: {
		<any information >
	},
	#  数组类型,配置用户的权限 
	roles: [{
		role: "<role>",
		db: "<database>"
	}......]
})

db.createUser({
	"user": "账号",
	"pwd": "密码",
	"roles": [{
		role: "角色",
		db: "所属数据库"
	}]
}) 


#  3.2 创建一个用户
db.createUser({
	user: "uaad",
	pwd: "uaad",
	roles: [
		{
			role: "userAdminAnyDatabase",
			db: "admin"
		}
	]
})

# 4. 重启服务
#    管理员创建完账号以后,需要重启mongo,并开启身份验证功能

#  关闭服务 
db.shutdowmServer()

5.4 创建普通用户

创建一个test数据库,然后为数据库添加一个 用户名和密码是user1的用户,并赋予该用户 对该数据库的读写操作权限

操作都在MongoDB安装bin目录下进行

5.4.1 MongoDB开启并连接服务

此处采用的是 配置文件的方式 开启的连接,有身份认证

1 启动MongoDB

# 1. 启动MongoDB
mongod -f mongodb.conf

2 新开一个命令窗口,连接启动 mongo 数据库

# 1.  启动mongo
mongo

# 2.  查看数据库(注意:此时是查询不到数据库的,必须要 开启身份认证 才可以查到数据)
show dbs

# 3.  开启身份验证
use admin
db.auth("admin","admin")

# 4. 再次查看 数据库就有数据了
show dbs

5.4.2 创建test数据库

# 如果有该数据库,就切换; 如果没有改数据库,就自动创建并切换到改数据库
use test 

5.4.3 创建用户

db.createUser({
	user: "user1",
	pwd: "user1",
	roles: [{
		role: "readWrite",
		db: "test"
	}]
})

4.5.4 身份认证

打开一个新的客户端连接,并切换至test数据库,进行身份验证

# 1. 开启服务
mongo

# 2.  切换到 test 数据库
use test

# 3. 开启身份认证
db.auth("user1","user1")

4.5.5 向test数据库插入文档

db.user.insert(
	{ "name": "zhangsan" }
)

4.5.5 查看user表中的用户

db.user.find()

5.5 更新用户

5.5.1 更新角色/权限

如果我们需要对已存在的用户角色进行修改,可以 使用 db.updateUser() 函数来更新用户角色

注意:执行该函数需要当前用户具有 userAdmin userAdminAnyDatabaseroot权限

# 语法 
db.updateUser("用户名",{"roles":[{"role":"角色名称","db":"数据库"},{"更新项2":"更新内容"}]})

# 例如给admin用户再添加 readWtiteAnyDatabase 和 dbAdminAnyDatabase 权限
db.updateUser("admin", {
	"roles": [{
		"role": "userAdminAnyDatabase",
		"db": "admin"
	}, {
		"role": "readWriteAnyDatabase",
		"db": "admin"
	}, {
		"role": "dbAdminAnyDatabase",
		"db": "admin"
	}]
})

再次查看 admin 用户的权限

use admin
show users

5.5.2 更改密码

更改密码有2种方式,更改密码时需要切换到该用户所在的数据库

需要具有 userAdmin userAdminAnyDatabaseroot角色权限的用户执行

# 方法一:
db.updateUser("用户名", {
	"pwd": "新密码"
})

# 方法二:
db.changeUserPassword("用户名", "新密码")

5.6 删除用户

使用 db.dropUser() 函数可以删除指定用户,删除成功后,返回true

db.dropUser("uaad")

删除用户时,需要切换到该用户所在的数据库

需要具有 userAdmin userAdminAnyDatabaseroot角色权限的用户才可以删除其他用户

image

6. 使用MogoDB GUI 可视化管理

方式一:

任务管理器 -- 服务 的方式开启 MongoDb,然后打开GUI可视化管理工具,连接Mongo即可

方式二:

使用 配置文件 mongod -f mongodb.conf 的方式开启 MongoDb,然后打开GUI可视化管理工具,连接Mongo即可

7. MongoDB数据库操作

7.1. 创建数据库

use 命令表示切换到数据库,如果数据库不存在,会自动创建数据库

# 语法
use databasename

# 创建一个名称为 order 的数据库
use order

7.2. 查询数据库

show dbs
# 或者
show databases

不同角色看见的数据库是不一样的,管理员可以看见所有的数据库,普通用户只能看见自己权限内的数据库

新创建的数据库,默认里面是没有数据的,所以当使用 show dbs 或者 show databases查看数据库的时候,是查询不到的;需要向此数据库新增一条数据才可以查到数据库

7.3. 删除数据库

db.DropDatabase()

删除数据库首先要切换到要删除的数据库中,使用 use database切换到指定的数据库,而且登陆用户必须具有 dbAdminAnyDatabase 权限

8. MongoDB 集合(表)操作

8.1. 创建集合

# 创建一个名为 order 的集合
db.createCollection('order')
  • name 集合的名称,optons 可选参数,指定有关内存、大小及索引的选项
  • 固定集合:有固定大小的集合,当达到最大值时,它会覆盖最早的文档
字段 类型 描述
capped 布尔 (可选)如果为true,则创建固定集合,而且当为true时,必须指定sise大小
size 数值 (可选)限定集合空间的大小,默认没有限制(以字节计)
autoIndexId 布尔 (可选)如果为true,自动在_id字段创建索引。默认true
max 数值 (可选)限制集合中,包含文档的最大数量。默认是没有限制

也可以通过直接插入数据,隐式创建集合 db.member.insert({"name":"zhangsan"}),自动创建集合 member 同时将数据插入到 集合中

# 方式一:当第一个文档被插入时,集合会被自动创建并包含该文档
db.member.insert({"name":"zhangsan"}) 

# 方式二:创建一个空集合;如果里面没有数据,查看集合(show tables 或者 show collections)时,是无法查到数据的;只有向该集合中插入文档,才可以查询到集合db.member

8.2. 查询集合

show tables
# 或者
show collections

如果集合里面没有数据,是查询不到集合的

8.3. 删除集合

db.database_name.drop()

9. MongoDB 文档(行)操作

9.1 插入文档

9.1.1 单条插入

可以使用 insert/insertOne/save 插入单条文档

# 插入 name=zhangsan 的一条文档:::

db.member.insert({"name":"zhangsan"}) 

db.member.insertOne({"name":"zhangsan"})

db.member.save({"name":"zhangsan"})


# 通过定义一个变量的方式 插入数据是非常方便的(推荐)
user1 = {
	"name": "zhangsan",
	"age": "18",
	"email": "[email protected]"
}
db.member.insert(user1)

save方法如果指定了 _id 字段就是更新文档,否则就是插入一条新的文档数据

9.1.1 批量插入

可以使用 insert/insertMany/save 插入多条文档,与单条插入的主要区别是:把单条插入时的函数参数的对象类型 {}变成数组类型 [{},{},{}]

db.member.insert({
	"name": "zhangsan"
}, {
	"name": "lisi"
}, {
	"name": "wangwu"
})


db.member.insertMany({
	"name": "zhangsan"
}, {
	"name": "lisi"
}, {
	"name": "wangwu"
})


db.member.save({
	"name": "zhangsan"
}, {
	"name": "lisi"
}, {
	"name": "wangwu"
})


# 通过定义一个变量的方式 插入数据是非常方便的( 推荐)
user1 = {
	"name": "zhangsan"
}
user2 = {
	"name": "lisi"
}
user3 = {
	"name": "wangwu"
}
db.member.insert([user1, user2, user3])

save方法如果指定了 _id 字段就是更新文档,否则就是插入一条新的文档数据

9.2 更新文档

通过 update系列函数或者save函数可以更新集合中的文档

update() 函数用于更新已经存在的文档,语法格式: db.database_name.update(query,update,options)

  • query:update的查询条件,类似于SQl 更新中的 where 条件
  • update:update的对象和一些更新的操作符等,相当于SQL更新中的set 部分,
  • options:upsert-可选,如果不存在update文档,是否插入该文档。true为插入,默认是false,不插入,
  • options:multi-可选,是否批量更新。true表示按照查询条件查询出来的多条记录全部更新;false是只更新找到的第一条记录,默认是false
user = {
	"name": "lichao",
	"age": "20",
	"hobbies": ["music", "runing", "read"],
	"addr": {
		"County": "China",
		"City": "ShangHai"
	}
}

# 修改单条
db.member.updateOne({"name":"张三"},user)

# 查找的数据如果是多条,只会修改第一条
db.menber.update({"name":"张三"},user) 等价于 修改单条数据

# 查找的数据如果是多条,修改所有匹配到的数据
db.menber.update({"name":"张三"},{"$set":user},false,true)  

# 修改多条
db.menber.updateMany({"name":"张三"},{"$set":user})  

9.3 查询文档

9.3.1 查询所有

# 1. 查询集合中的所有
db.database_name.find()

# 2. 查询集合中的所有(去重)
db.database_name.distinct("name")

# 3. 查询集合中的所有(以格式化的展示数据)
db.database_name.find().pretty()

# 4. 查询name=zhangsan的所有
db.database_name.find({name:'zhangsan'})

# 5. 只显示name字段 查询所有数据
db.database_name.find({},{name:1})

# 6. 除了name字段,其余的字段都显示, 查询所有数据
db.database_name.find({},{name:0})  

9.3.2 比较运算符查询

SQL运算符 MongoDB运算符
= =
!= "$ne"
> "$gt"
< "$lt"
>= "$gte"
<= "$lte"
# select * from user where id=3
db.user.find({"_id":"3"})

# select * from user where id!=3
db.user.find({"_id":{"$ne":3}})

# select * from user where id>3
db.user.find({"_id":{"$gt":3}})

# select * from user where id<3
db.user.find({"_id":{"$lt":3}})

9.3.3 逻辑运算查询

MongoDB中用 ,分割多个条件是and关系,或者直接用 $and $or $not (与或非)

#  select * from user where id >= 3 and id <= 10
db.user.find({
	"_id": {
		"$gte": 3,
		"$lte": 10
	}
})

#  select * from user where id >= 3 and id <= 10 and age >= 30
db.user.find({
	"_id": {
		"$gte": 3,
		"$lte": 10
	}
}, {
	"age": {
		"$gte": 30
	}
})
 # 或者
 db.user.find({
	"$and": [{
		"_id": {
			"$gte": 3,
			"$lte": 10
		}
	}, {
		"age": {
			"$gte": 30
		}
	}]
}) 

# select * from user where id >= 3 and id <= 10 or id <= 20 or name = 'lisi'
db.user.find({
	"$or": [{
		"_id": {
			"$gte": 3,
			"$lte": 10
		}
	}, {
		"_id": {
			"$lte": 20
		}
	}, {
		"name": "lisi"
	}]
}) 

# select * from user where id % 2 == 1 
db.user.find({
	"_id": {
		"$mod": [2, 1]
	}
}) 

# select * from user where id % 2 != 1 
db.user.find({
	"_id": {
		"$not": {
			"$mod": [2, 1]
		}
	}
})

9.3.4 $type操作符查询

33

# 查询name是字符串类型的数据
db.user.find({"name":{"$type":2}})

9.3.5 正则查询

主要是定义在 / /

# 查询 name是 z开头  u或者n 结尾的名称
# select * from user where name regexp '^z.*?(u|n)$'

db.user.find({'name':/^z.*?(u|n)$/i})

9.3.6 投影查询

只选择必要的字段,而不是整个文档所有的字段,设置字段列表值为1或0 即可

1显示字段 0隐藏字段 _id默认显示出来

# select name,age from user where id=3
db.user.find({"_id":3},{"name":1,"age":1})

# 如果想要 _id也隐藏,设置 _id:
db.user.find({"_id":3},{"_id":0,"name":1,"age":1}) 

9.3.7 数组查询

# 1. 查询hobbies中有read的人
db.user.find({"hobbies":"read"})

# 2. 查询hobbies中既有read也有tea爱好的人
db.user.find({"hobbies":{"$all":["read","tea"]}})

# 3. 查询索引为第二个 爱好为tea的人 (索引从0开始)
db.user.find({"hobbies.2":"tea"})

# 4. 查看所有人的第一个到第三个爱好(左闭右开)
db.user.find({},
	// 查询条件为所有  
	{
		"_id": 0,
		"name": 0,
		"age": 0 "hobbies": {
			"$slice": [0, 2]
		}
	})
	
	
# 5. 查看所有人的最后2个爱好
db.user.find({},
	// 查询条件为所有
	{
		"_id": 0,
		"name": 0,
		"age": 0 "hobbies": {
			"$slice": -2
		}
	})	
	
# 6 查询子文档有 "County": "China"的人,
user = {
	"name": "lichao",
	"age": "20",
	"hobbies": ["music", "runing", "read"],
	"addr": {
		"County": "China",
		"City": "ShangHai"
	}
}
db.user.find({
	"addr.County": "China"
})	

3.8 排序查询

1升序

-1降序

# 1 按照姓名正序排列
db.user.find().sort({name:1})

# 2 按照 年龄 倒序,id正序 排列
db.user.find().sort({age:-1,_id:1})

9.3.9 分页查询

limit表示取多少个文档:每页显示多少条数据

skip表示跳过几个文档

db.user.find().skip((pageNum-1)*pageSize).limit(pageSize)

# pageSize: 每页显示多少条数据 (此处是每页显示2条数据)
# pageNum:  第几页(当前是第几页)
#  1. 前两个(第一页)
db.user.find().limit(2).skip(0)

#  2. 第三个和第四个(第二页)
db.user.find().limit(2).skip(2)

#  3. 第五个和第六个(第三页)
db.user.find().limit(2).skip(4)

9.3.10 统计

# 方式一:查询id大于3的人数
db.user.count({"_id":{"$gt":3}})

# 方式一:查询id大于3的人数
db.user.find({"_id":{"$gt":3}}).count()

9.3.11 聚合查询

语法:

db.集合名称.aggregate([{管道:{表达式}}     ....])

1 常用管道

$group:将集合中的文档分组,用于统计结果
$match:过滤数据,只要输出符合条件的文档
$sort :聚合数据进一步排序
$skip:跳过指定文档数
$limit:限制集合数据返回文档数

2 常用表达式

$sum:计算总和,$sum:1 同 count 统计
$avg:计算平均值
$min :获取集合中所有文档对应值的最小值
$max :获取集合中所有文档对应值的最大值
$push :在结果文档中插入值到一个数组中
$addToSet :在结果文档中插入值到一个数组中, 但不创建副本
$first :根据资源文档的排序获取第一个文档数据
$last :根据资源文档的排序获取最后一个文档数据

3 $match和$group

$group:将集合中的文档分组,用于统计结果,相当于 mysql中 的 group by
$match:过滤数据,只要输出符合条件的文档,,相当于 mysql中 的 where

可以使用任何查询操作符  $gt $lt $in 等
{"$match":{"字段":"条件"}} 


{"$group":{"_id":分组字段,"新的字段名":聚合操作符}}

案例展示:

# 数据结构参考	
	emp1 = {
		"_id": 1,
		"name": "张三",
		"sex": "male",
		"age": "20",
		"hire_date": "20151212",  # 入职时间
		"post": "公务员",          # 职位
		"salary": "7800.00",      # 薪资
	}


#  1. 查询职位为公务员的员工
#  select * from db.emp where post="公务员"
db.emp.aggregate([{"$match"}:{"post":"公务员"}])


#  2. 以post分组,查询id大于3的所有员工的平均工资
#  select * from db.emp where id>3 group by post
db.emp.aggregate([  "$match":{"_id":{"$gt":3}},  {"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}}])


#  3. post分组,查询id大于3的所有员工的平均工资,平均工资大于10000
#  select * from db.emp where id>3 group by post having avg(salary) > 10000
db.emp.aggregate([  "$match":{"_id":{"$gt":3}},  {"$group":{"_id":"$post","avg_salary":{"$avg":"$salary"}}},  "$match":{"avg_salary":{"$gt":10000 }}])


#  4. group分组:group函数的_id字段即可
# 按照职位分组
{"$group":{"_id":"$post"}}  
# 按照性别分组
{"$group":{"_id":"$sex"}} 
# 按照多个字段分组
{"$group":{"_id":{"state":"$state","sex":"$sex"}}}  


#  5. 以post分组,获取所有员工中的最大薪资
#  select post,max(salary) from db.emp group by post
db.emp.aggregate([  {"$group":{"_id":"$post","max_salary":{"$max":"$salary"}}},])

#  6. 获取每个部分的最大薪资和最小薪资
db.emp.aggregate([  {"$group":{"_id":"$post","max_salary":{"$max":"$salary","mix_salary":{"$mix":"$salary"}}},])

#  7. 获取每个部门的总工资,并倒序排序
db.emp.aggregate([  {"$group":{"_id":"$post","count":{"$sum":"$salary"},{"$sort":"count":1}}},])

#  8. 求每个部门的总人数
db.emp.aggregate([  {"$group":{"_id":"$post","count":{"$sum":1},{"$sort":"count":1}}},])

# 9. 查询岗位名以及各岗位内的员工姓名
select post,group_concat(name) from db.emp group by post
# 包含重复的数据
db.emp.aggregate([  {"$group":{"_id":"$post","names":{"$push":"$name"}}},])

# 去除重复的数据
db.emp.aggregate([  {"$group":{"_id":"$post","names":{"$addToSet":"$name"}}},])

4 $project

用于投射,即设定该键值对是否保留,1保留 0不保留

可对原有的键值对做操作后增加自定义表达式(查询哪里要显示的列)

{"$project":{"要保留的字段名":1,"要去掉的字段名":0,"新增的字段名":"表达式"}}
select name, post, (age + 1) as new_age from db1.emp
db.emp.aggregate([{
	$project: {
		"name": 1,
		"post": 1,
		"new_age": {
			"$add": {
				"$age": 1
			}
		}
	}
}])

5 $sort $limit $skip

排序:{"$sort":{"字段名":1,"字段名":-1}}

限制:{"$limit":n} 限制多少个文档

跳过:{"$skip":n} 跳过多少个文档

#  1. 获取平均工资最高的前2个部门
db.emp.aggregate([{
	"$group": {
		"_id": "$post",
		"平均工资": {
			"$avg": "$salary"
		}
	}
}, {
	"$sort": {
		"平均工资": -1
	}
}, {
	"$limit": 2
}])


#  2. 获取平均工资最高的第2个部门
db.emp.aggregate([{
	"$group": {
		"_id": "$post",
		"平均工资": {
			"$avg": "$salary"
		}
	}
}, {
	"$sort": {
		"平均工资": -1
	}
}, {
	"$limit": 2
}, {
	"$skip": 1
}])

6 $sample:随机选取n个

# 随机获取3个文档
db.emp.aggregate([{
	"$sample": {
		size: 3
	}
}])

7 $concat $substr $toLower $toUpper

{"$substr":[$值为字符串的字段名,起始位置,截取几个字节]}

{"$toUpper":expr}  # 转大写

{"$toLower":expr}  # 转小写

{"$concat":[expr1,expr2,...,exprN]} # 指定的表达式或字符串连接在一起返回

1. 截取字符串db.emp.aggregate([{$project:{"_id":0,"str":{$substr:["$sex",0,2]}}}])

2. 拼接db.emp.aggregate([{$project:{"name":1, "post":1,"name_sex":{$concat:["$name","测试拼接数","$sex"]}}}])

3. 将性别的英文转为大写
db.emp.aggregate([{"$project":{"sex":{"$toUpper":"$sex"}}}])

8 索引---实现高效的数据查询

索引是一种排序好的便于快速查询的数据结构,可以帮助数据库高效的查询数据

索引的优缺点:

  • 优点:提高数据查询的效率,降低数据库的IO成本;通过索引对数据进行排序,降低数据排序的成本,降低CPU的消耗
  • 缺点:占用磁盘空间;大量索引影响SQL语句效率,因为每次插入和修改数据都需要更新索引

选择设置索引的规则:

    1. 为常做条件、排序、分组的字段建立索引
    1. 选择唯一性索引
    1. 选择较小的数据列,为较长的字符串使用前缀索引
创建索引
db.datatabase_name.ensureIndex({KEY:1}) 
    KEY是要指定索引的字段名;
    1是升序 -1是降序 

1.1 按照降序将name设置为索引    
    例如: db.emp.ensureIndex({"name":-1})  

1.2 也可以指定所建立的索引的名称(类似于索引的别名)    
    例如: db.emp.ensureIndex({"name":-1},{"name":"nameIndex"})    
    
1.3 给name和age添加组合索引    
    例如: db.emp.ensureIndex({"name":-1,"age":1}) 
    
1.4 创建唯一索引   
    db.emp.createIndex({"name":-1,"age":1}) 与 1.3创建组合索引是是一样的       
	db.emp.createIndex({name:1}, {unique: "name"}) 当你设置字段为唯一索引时,那么此字段的值就是唯一的    
	
查询索引
db.emp.getIndexes()
删除索引
db.database_name.dropIndex(indexname)
   例如: db.emp.dropIndex("nameIndex")db.database_name.dropIndexes(); 
   # 删除全部索引,但是系统默认的索引还是存在的
   
分析索引
db.database_name.find().explain('executionStats')

扫描方式:    > COLLSCAN 全表扫描    > IXSCAN  索引扫描    > FETCH   根据索引去检索指定document

分析索引:
image

9.4 删除文档:remove()

remove()函数用来移除集合中的文档,语法如下:

db.database_name.remove(<query>,{justOne:<boolean>})

参数:

query:删除文档的条件(可选)

justOne:true,只删除一个文档;false删除所有匹配的文档;(可选)

删除所有

db.database_name.remove({}) 
# 或者
db.database_name.deleteMany({})

只删除符合条件的第一个

db.database_name.deleteOne(<query>)

10. MongoDB备份和还原

10.1 备份数据库

# 备份导出数据语法: 
mongodump -h -port -u -p -d -o-h 		  
    host  服务器IP地址(一般不写 默认本机)
    -port 		  端口(一般不写 默认27017)
    -u     user       账号
    -p      pwd       密码-d  
    database     数据库(数据库不写则导出全局)
    -o     open      

# 备份到指定目录下备份所有数据库
mongodump -u admin -p admin888 -o D:\mongodb\bak,

# 备份指定数据库 shop
mongodump -u admin -p admin888 -d shop -o D:\mongodb\bak2

10.2 还原数据库

# 还原数据裤语法:
mongorestore -h -port -u -p  -d --drop 

# 备份数据目录-h -port -u -p-d       
# 不写则还原全部数据库--drop   

# 先删除数据库再导入还原所有数据
mongorestore -u admin -p admin888 --drop D:\mongodb\bak,

# 还原指定数据
mongorestore -u shop2 -p admin888 -d shop --drop D:\mongodb\bak2\shop

11. nodejs操作mongoose

mongoose 官网

11.1 简介

mongoose 是node中提供操作MongoDB的模块,它是基于 MongoDB 官方的 mongodb 包进一步做了封装,可以提高开发效率,让你操作 MongoDB 数据库更方便

能够通过node语法实现MongoDB数据库增删改查,从而实现用node写程序来管理MongoDB数据库

schema: 约束字段/列数据

主要作用:用来约束MongoDB文档数据(哪些字段必须,哪些字段可选的)

model:模型

一个模型 对应 一个集合,主要用它来实现数据的增删改查

通过模型来管理集合中的数据

11.2 mongoose使用

1 项目创建和下载安装依赖

# 1.  创建项目目录
mkdir mongodb-demo

# 2. 进入项目目录
cd mongodb-demo

# 3. 初始化项目
npm init -y

# 4. 下载安装mongoose第三方模块
#    --save 可以省略,npm 5.0版本以后
npm install mongoose --save  # 或者 npm i mongoose  

2 mongoose 构建

// 0. 引入第三方模块 mongoose
const mongoose = require('mongoose');

// 1. 连接本机数据库 school ,如果指定连接的数据库不存在,当你插入第一条数据之后就会自动被创建出来
mongoose.connect('mongodb://localhost/school')

// 2. 设置集合(表)的数据架构   Schema
var Schema = mongoose.Schema({
	name: {
		type: String,
		required: true, // 必填     
	},
	age: Number, // 年龄
	// 性别
	gender: {
		type: Number,
		enum: [0, 1], // 枚举数据  
		default: 0, // 默认值     
	},
	job: String, // 职位
});

/*
    3. 将文档结构发布 一个 名为 student 的模型
    mongoose.model 方法就是用来将一个架构发布为 model
	     第一个参数:传入一个大写名词单数字符串用来表示你的数据库名称,mongoose 会自动将大写名词的字符串生成 小写复数 的集合名称:例如这里的 Student 最终会变为 students 集合名称      
	    
	    第二个参数:架构 Schema   
        
		返回值:模型构造函数    
*/
var model_student = mongoose.model('Student', Schema);

3 增删改查

3.1 保存/新增 数据 save

//  创建实例对象
var stuObj = new model_student({
	name: '李玉霞',
	age: 23,
	gender: 0,
	job: '医生'
});

// 将数据对象 保存 到集合    
stuObj.save(function(err, result) {
	if (err) return console.error(err);
	console.log('保存成功');
});

3.2 查询数据

// 1.  查询 所有 数据    
model_student.find(function(err, result) {
	if (err) return console.error(err);
	console.log(result);
})

// 2.  查询 name = 'zhangsan' 的所有数据   
model_student.find({
	name: 'zhangsan'
}, function(err, result) {
		if (err) return console.error(err);
	console.log(result);
})

// 3. 查询 name = 'zhangsan' 一条的数据       
model_student.findOne({
	name: 'zhangsan'
}, function(err, result) {
	if (err) return console.error(err);
	console.log(result);
})

3.3 删除数据

// 1.  删除 name = 'zhangsan' 的所有数据       
model_student.remove({
	name: 'zhangsan'
}, function(err, result) {
	if (err) return console.error(err);
	console.log('删除成功');
})

// 根据 id 删除一个
model_student.findByIdAndRemove(id,[options],callback)

// 根据 条件 删除一个
model_student.findOneAndRemove(id,[options],callback)

3.4 更新数据

// 根据id 更新数据         
model_student.findByIdAndUpdate('6073c730a1cf34434845a151', {
	name: 'lisi'
}, function(err, result) {
	if (err) return console.error(err);
	console.log('更新成功');
})

// 根据条件更新所有
model_student.update(conditions,doc,[,options],callback)

// 根据指定的条件更新一个
model_student.findOneAndUpdate(conditions,doc,[,options],callback)

// 根据id更新一个
model_student.findByIdAndUpdate(id,doc,[,options],callback)

3.5 分页查询,每页显示2条数据

model_student.find({}).skip(1).limit(2).then(res => {
	console.log(res) 
}).catch(err => {
	console.log(err) 
})

标签:name,MongoDB,数据库,db,基础知识,文档,id
From: https://www.cnblogs.com/songxia/p/17752706.html

相关文章

  • 01webpack基础知识
    1概述1.1什么是webpack1、webpack是一种前端资源构建工具,一个静态模块打包器(modulebundler)。在webpack看来,前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理。它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)2、webpack是一个前......
  • 计算机基础知识
    计算机基础知识计算机简介​ 计算机俗称电脑,是第二次世界战争时,美国国防部利用它来进行弹道计算。第一台通用计算机叫做:ENIAC。当时计算机是一个庞然大物,用了18000个电子管,占地170平方米,重达30吨,耗电功率约150千瓦,每秒钟可进行5000次运算。​ 随着时间和科技的不断进步,直到发展......
  • MongoDB下载安装入门
    MongoDB下载安装入门一.MongoDB下载安装mongodb官网下载不了,MongoDB下载、安装、配置、使用,如何下载MongoDB数据库,MongoDB入门-CSDN博客按照文章一→六:安装,下载,环境变量配置等等MongoDBv4.2版安装目录:C:\ProgramFiles\MongoDB\Server\4.2\bin二.安全认证注意!!!一定要......
  • mongodb慢查询对内存和CPU的影响
    所得结果均为ChatGPT所得,只是用来记录好复习对内存的影响数据加载到内存:MongoDB使用内存来缓存最频繁访问的数据,以提高查询性能。这个缓存通常称为"工作集"。当一个查询需要访问某些数据时,MongoDB会尝试从内存中获取数据,这比从磁盘读取数据要快得多。慢查询导致数据逐出:当......
  • 【最佳实践】MongoDB导出导入数据
    首先说一下这个3节点MongoDB集群各个维度的数据规模:1、dataSize:1.9T2、storageSize:600G3、全量备份-加压缩开关:186G,耗时8h4、全量备份-不加压缩开关:1.8T,耗时4h27m具体导出的语法比较简单,此处不再赘述,本文重点描述导入的优化过程,最后给出导入的最佳实践。■2023-09-13......
  • 【最佳实践】MongoDB导入数据时重建索引
    MongoDB一个广为诟病的问题是,大量数据resotore时索引重建非常缓慢,实测5000万的集合如果有3个以上的索引需要恢复,几乎没法成功,而且resotore时如果选择创建索引也会存在索引不生效的问题,种种情况表明,MongoDB的一些默认设置存在明显不合理之处。当然,深入理解后总会有办法解决这些问......
  • Kubeflow基础知识
    kubeflow基础知识kubeflow简介kubeflow是谷歌开源的MLOps开源平台,其中包含的不同组件代表了机器学习生命周期的不同阶段。下图是kubeflow组织ML工作流程:kubeflow组件介绍1.kubeflowPipelinespipelines是对机器学习工作流的一种描述,当运行一个pipeline时系统会启动一......
  • 【一】基础知识
    【小结】1.汇编指令是机器语言的助记符,同机器指令一一对应。2.每一种CPU都有自己的汇编指令集。3.CPU可以直接使用的信息在存储器中存放4.在存储器中指令和数据没有任何区别,都是二进制信息。5.存储单元从零开始顺序编号。6.一个存储单元可以存储8个bit,即8位二进制数。7.1B......
  • java基础知识总结,javaweb参考资料大全
    Java基础知识总结写代码:1,明确需求。我要做什么?2,分析思路。我要怎么做?1,2,3。3,确定步骤。每一个思路部分用到哪些语句,方法,和对象。4,代码实现。用具体的java语言代码把思路体现出来。 学习新技术的四点:1,该技术是什么?2,该技术有什么特点(使用注意):3,该技术怎么使用。demo4,该技术什么时......
  • WIN11 安装 SQL Server 2019,SQLSERVER2022, MYSQL 8.0 ,Docker,Mongodb失败故障分析
    最近研究数据库性能调优遇到各种数据库各种装不上,不知道熬了多少根软白沙,熬了多少颗张三疯,问了多少AI,查了多少网页,熬了两天,终于搞明白了一件事:那就是WIN11ONARM(因为拿的是MACPROM2做.NET平台开发安装)SQLSERVER2019,SQLSERVER2022,MYSQL8.0,Docker,Mongodb失败故障分析,最终极......