MongoDB入门

1.MongoDB 基本概念详解

2.MongoDB 快速实战
3.MongoDB 核心操作与原理详解

Mongo 是 humongous 的中间部分,在英文里是"巨大无比"的意思。所以 MongoDB 可以翻译

成"巨大无比的数据库",更优雅的叫法是"海量数据库"。Mongodb是一款非关系型 数据库,说

到非关系型数据库,区别于关系型数据库最显著的特征就是没有SQL语句,数据没有固定的数据类

型,关系数据库的所使用的SQL语句自从 IBM 发明出来以后,已经有 40 多年的历史了,但是时至今

日,开发程序员一般不太喜欢这个东西,因为它的基本理念和程序员编程的想法不一致。后来所谓的

NoSQL 风,指的就是那些不用 SQL 作为查询语言的数据存储系统,而文档数据库 MongoDB 正是

NoSQL 的代表。

看一下当下 数据库的排名就会发现,目前排在Mongodb数据库前面的无一例外是老牌的关系型数据库,而在No SQL序列中,Mongodb排名第一,且有上升的趋势

我们在正式进入Mongodb的学习之前,先来了解一下,MongoDB都有哪些特点,为什么要引入
MongoDB以及MongoDB和关系型数据库的差异

  1. MongoDB中的记录是一个文档,它是由字段和值对组成的数据结构。MongoDB文档类似于
    JSON对象。字段的值可以包括其他文档,数组和文档数组。MongoDB数据模型和你的对象在内存中的表现形式一样,一目了然的对象模型。

2.同一个集合中可以包含不同字段(类型)的文档对象:同一个集合的字段可能不同

3.线上修改数据模式,修改时应用与数据库都无须下线

关系型数据库和文档型数据库主要概念对应

MongoDB安装:

bash 复制代码
1. 获取安装包
1 wget https://fastdl.mongodb.org/linux/mongodb‐linux‐x86_64‐rhel70‐4.4.2.tgz
2. 进行解压
1 tar ‐xvzf mongodb‐linux‐x86_64‐rhel70‐4.4.2.tgz
3. 添加到系统执行路径下面( ~/.bashrc)
1 export PATH=$PATH:<你机器MongoDB bin目录,如:/usr/local/mongodb/mongodb‐linux‐x86_
64‐rhel70‐4.4.2/bin>
执行 source ~/.bashrc
4. 创建数据目录
1 mkdir ‐p /data/db # 这个路径是MongoDB默认的数据存放路径
5. 启动MongoDB服务
1 mongod # 如果你不希望使用的默认数据目录可以通过 添加 ‐‐dbpath 参数指定路径
或者从后台启动
mongod --logpath /data/db/logpath/output --fork
需要指定 --logpath , 或者--syslog

客户端使用( mongo shell, 用来操作MongoDB的javascript客户端界面 ):

bash 复制代码
1. 连接服务
1 mongo ‐‐host <HOSTNAME> ‐‐port <PORT>
2 # 如果在本机使用的都是默认参数,也可以直接忽略所有参数
2. 设置密码
1 use admin # 设置密码需要切换到admin库
2
3 db.createUser(
4 {
5 user: "gj",
6 pwd: "gj123",
7 roles: [ "root" ]
8 }
9 )
10 show users # 查看所有用户信息
3. 停服务
1 db.shutdownServer() # 停掉服务
4. exit 退出 mongo
5. 以授权模式启动
1 mongod ‐‐auth
6. 授权方式连接
1 mongo ‐u gj
  1. 连上之后就可以进行操作:

连上之后先来看看都有哪些操作

bash 复制代码
安全说明:
MongoDB基于安全性考虑,默认安装后只会绑定本地回环 IP 127.0.0.1, 可以通过启动服务时,指定
绑定的IP 如 只允许通过 IP: 192.168.109.200 访问,
1 mongod ‐‐bind_ip 192.168.109.200
这时登录需要通过
1 mongo ‐host 192.168.109.200 ‐u gj

通过命令访问 MongoDB

bash 复制代码
1 输入 db # 显示当前所在的数据库
2
3 use example # 切换数据库
4
5
UI客户端访问:
https://docs.mongodb.com/compass/master/install
基本操作:添加数据
1 db.集合.insertOne(<JSON对象>) // 添加单个文档
2 db.集合.insertMany([{<JSON对象1>},{<JSON对象2>}]) // 批量添加文档
3 db.集合.insert() // 添加单个文档
开始创建文档
1 db.collection.insertOne(
2 doc ,
3 {
4 writeConcern: 安全级别 // 可选字段
5 }
6 )
writeConcern 定义了本次文档创建操作的安全写级别简单来说, 安全写级别用来判断一次数据库写
入操作是否成功,安全写级别越高,丢失数据的风险就越低,然而写入操作的延迟也可能更高。
writeConcern 决定一个写操作落到多少个节点上才算成功。 writeConcern的取值包括
0: 发起写操作,不关心是否成功
1- 集群中最大数据节点数: 写操作需要被复制到指定节点数才算成功
majority: 写操作需要被复制到大多数节点上才算成功
发起写操作的程序将阻塞到写操作到达指定的节点数为止
1 db.emp.insertOne(
2 {
3 name:"zhangsan",
4 age:20,
5 sex:"m"}
6 );

插入文档时,如果没有显示指定主键,MongoDB将默认创建一个主键,字段固定为_id,ObjectId()

可以快速生成的12字节id 作为主键,ObjectId 前四个字节代表了主键生成的时间,精确到秒。主键

ID在客户端驱动生成,一定程度上代表了顺序性,但不保证顺序性, 可以通过ObjectId("id

值").getTimestamp() 获取创建时间。

bash 复制代码
创建多个文档
1 db.collection.insertMany(
2 [ {doc } , {doc }, ....],
3 {
4 writeConcern: doc,
5 ordered: true/false
6 }
7 )
ordered: 觉得是否按顺序进行写入
顺序写入时,一旦遇到错误,便会退出,剩余的文档无论正确与否,都不会写入
乱序写入,则只要文档可以正确写入就会正确写入,不管前面的文档是否是错误的文档
MongoDB以集合(collection)的形式组织数据,collection 相当于关系型数据库中的表,如果
collection不存在,当你对不存在的collection进行操作时,将会自动创建一个collection
如下:
将会创建一个 inventory 集合,并且插入 5 个文档
1 db.inventory.insertMany([
2 { item: "journal", qty: 25, status: "A", size: { h: 14, w: 21, uom: "cm" }, tags:
[ "blank", "red" ] },
3 { item: "notebook", qty: 50, status: "A", size: { h: 8.5, w: 11, uom: "in" }, tag
s: [ "red", "blank" ] },
4 { item: "paper", qty: 10, status: "D", size: { h: 8.5, w: 11, uom: "in" }, tags:
[ "red", "blank", "plain" ] },
5 { item: "planner", qty: 0, status: "D", size: { h: 22.85, w: 30, uom: "cm" }, tag
s: [ "blank", "red" ] },
6 { item: "postcard", qty: 45, status: "A", size: { h: 10, w: 15.25, uom: "cm" }, t
ags: [ "blue" ] }
7 ]);
上述操作返回一个包含确认指示符的文档和一个包含每个成功插入文档的_id的数组

整个文档查询:

db.inventory.find({}) 查询所有的文档

db.inventory.find({}).pretty() 返回格式化后的文档

条件查询:

  1. 精准等值查询

db.inventory.find( { status: "D" } );

db.inventory.find( { qty: 0 } );

  1. 多条件查询

db.inventory.find( { qty: 0, status: "D" } );

  1. 嵌套对象精准查询

db.inventory.find( { "size.uom": "in" } );

  1. 返回指定字段

db.inventory.find( { }, { item: 1, status: 1 } );

默认会返回_id 字段, 同样可以通过指定 _id:0 ,不返回_id 字段

  1. 条件查询 and

db.inventory.find({$and:[{"qty":"0"},{"status":"A"}]}).pretty();

  1. 条件查询 or

db.inventory.find({$or:[{"qty":"0"},{"status":"A"}]}).pretty();

Mongo查询条件和SQL查询对照表

insertOne, inertMany, insert 的区别

insertOne, 和 insertMany命令不支持 explain命令

insert支持 explain命令

复合主键

bash 复制代码
可以使用文档作为复合主键
1 db.demeDoc.insert(
2 {
3 _id: { product_name: 1, product_type: 2},
4 supplierId:" 001",
5 create_Time: new Date()
6 }
7 )
注意复合主键,字段顺序换了,会当做不同的对象被创建,即使内容完全一致

逻辑操作符匹配

$not : 匹配筛选条件不成立的文档

$and : 匹配多个筛选条件同时满足的文档

$or : 匹配至少一个筛选条件成立的文档

$nor : 匹配多个筛选条件全部不满足的文档

bash 复制代码
构造一组数据:
db.members.insertMany([
{
nickName:"曹操",
points:1000
},
{
nickName:"刘备",
points:500
}
]);
1 $not
用法:
1 { field: { $not : { operator‐expression} }}
积分不小于100 的
1 db.members.find({points: { $not: { $lt: 100}}} );
$not 也会筛选出并不包含查询字段的文档
1 $and
用法
1 { $and : [ condition expression1 , condition expression2 ..... ]}
昵称等于曹操, 积分大于 1000 的文档
1 db.members.find({$and : [ {nickName:{ $eq : "曹操"}}, {points:{ $gt:1000}}]});
当作用在不同的字段上时 可以省略 $and
1 db.members.find({nickName:{ $eq : "曹操"}, points:{ $gt:1000}});
当作用在同一个字段上面时可以简化为
1 db.members.find({points:{ $gte:1000, $lte:2000}});
1 $or
用法
1 { $or :{ condition1, condition2, condition3,... }}
1 db.members.find(
2 {$or : [
3 {nickName:{ $eq : "刘备"}},
4 {points:{ $gt:1000}}]}
5 );
如果都是等值查询的话, $or 和 $in 结果是一样的
字段匹配
$exists:匹配包含查询字段的文档
1 { field : {$exists: <boolean>} }
文档游标
1 cursor.count( applySkipLimit)
默认情况下 , 这里的count不会考虑 skip 和 limit的效果,如果希望考虑 limit 和 skip ,需要设置
为 true。 分布式环境下,count 不保证数据的绝对正确
1 cursor.sort( <doc>)
这里的<doc> 定义了排序的要求
1 { field: ordering}
1 表示由小到大, -1 表示逆向排序
当同时应用 sort, skip, limit 时 ,应用的顺序为 sort, skip, limit
文档投影: 可以有选择性的返回数据
1 db.collection.find( 查询条件, 投影设置)
投影设置:{ field: < 1 :1 表示需要返回, 0: 表示不需要返回 , 只能为 0,或者1 , 非主键字
段,不能同时混选0 或 1>}
1 db.members.find({},{_id:0 ,nickName:1, points:1})
1 db.members.find({},{_id:0 ,nickName:1, points:0})
可以使用 $slice 返回数组中的部分元素
如, 先添加一个数组元素的文档
1 db.members.insertOne(
2 {
3 _id: {uid:3,accountType: "qq"},
4 nickName:"张飞",
5 points:1200,
6 address:[
7 {address:"xxx",post_no:0000},
8 {address:"yyyyy",post_no:0002}
9 ]}
10 );
返回数组的第一个元素
1 db.members.find(
2 {},
3 {_id:0,
4 nickName:1,
5 points:1,
6 address:
7 {$slice:1}
8 });
返回倒数第一个
1 db.members.find(
2 {},
3 {_id:0,
4 nickName:1,
5 points:1,
6 address:{$slice:‐1}}
7 );
slice: 值
1: 数组第一个元素
-1:最后一个元素
-2:最后两个元素
slice[ 1,2 ] : skip, limit 对应的关系
还可以使用 elementMatch 进行数组元素进行匹配
添加一组数据
1 db.members.insertOne(
2 {
3 _id: {uid:4,accountType: "qq"},
4 nickName:"张三",
5 points:1200,
6 tag:["student","00","IT"]}
7 );
查询tag数组中第一个匹配"00" 的元素
1 db.members.find(
2 {},
3 {_id:0,
4 nickName:1,
5 points:1,
6 tag: { $elemMatch: {$eq: "00" } }
7 });
$elemMatch 和 $ 操作符可以返回数组字段中满足条件的第一个元素
更新操作
updateOne/updateMany 方法要求更新条件部分必须具有以下之一,否则将报错
$set 给符合条件的文档新增一个字段,有该字段则修改其值
$unset 给符合条件的文档,删除一个字段
$push: 增加一个对象到数组底部
$pop:从数组底部删除一个对象
$pull:如果匹配指定的值,从数组中删除相应的对象
$pullAll:如果匹配任意的值,从数据中删除相应的对象
$addToSet:如果不存在则增加一个值到数组
更新文档:
单条插入数据, 插入两跳
1 db.userInfo.insert([
2 { name:"zhansan",
3 tag:["90","Programmer","PhotoGrapher"]
4 },
5 { name:"lisi",
6 tag:["90","Accountant","PhotoGrapher"]
7 }]);
将tag 中有90 的文档,增加一个字段: flag: 1
1 db.userInfo.updateMany(
2 {tag:"90"},
3 {$set:{flag:1}}
4 );
只修改一个则用
1 db.userInfo.updateOne(
2 {tag:"90"},
3 {$set:{flag:2}}
4 );
基于上面这两条数据,可以来查询一下数组中的元素
userInfo 中,会计和程序员的文档
db.userInfo.find(
{$or:
[
{tag:"Accountant"},
{tag:"Programmer"}
]
});
userInfo 中,90后的文档
1 db.userInfo.find({tag:"90"});
更新文档
1 db.collection.update( <query>,<update>,<options>)
<query> 定义了更新时的筛选条件
<update> 文档提供了更新内容
<options> 声明了一些更新操作的参数
更新文档操作只会作用在第一个匹配的文档上
如果<update> 不包含任何更新操作符,则会直接使用update 文档替换集合中符合文档筛选条件的
文档
更新特定字段
db.collection.update( <query>,<update>,<options>)
<query> 定义了更新时的筛选条件
<update> 文档提供了更新内容
<options> 声明了一些更新操作的参数
如果<update>只包含更新操作符,db.collection.update() 将会使用update更新集合中符合
<query>筛选条件的文档中的特定字段。
默认只会更新第一个匹配的值,可以通过设置 options {multi: true} 设置匹配多个文档并更新
1 db.doc.update(
2 {name:"zhangsan"},
3 {$set:{ flag: 1 }},
4 {multi:true}
5 );
更新操作符
$set 更新或新增字段
$unset删除字段
$rename 重命名字段
$inc 加减字段值
$mul 相乘字段值
$min 采用最小值
$max 次用最大值
删除文档
1 db.collection.remove(<query>,<options>)
默认情况下,会删除所有满足条件的文档, 可以设定参数 { justOne:true},只会删除满足添加的第一
条文档
删除集合
1 db.collection.drop( { writeConcern:<doc>})
<doc> 定义了本次删除集合操作的安全写级别
这个指令不但删除集合内的所有文档,且删除集合的索引
db.collection.remove 只会删除所有的文档,直接使用remve删除所有文档效率比较低,可以使用
drop 删除集合,才重新创建集合以及索引。
查询数组中的对象
加两行数据,文档中存在数组,且数组中你的元素为对象
1 db.userInfo.insertMany([
2 { name:"wangwu",
3 tag: ["90","accountant","PhotoGrapher"],
4 address:[{province:"hunan",city:"changsha"},{province:"hubei",city:"wuhan"}]},
5 { name:"zhaoliu",
6 tag: ["90","accountant","PhotoGrapher"],
7 address:[{province:"hunan",city:"changsha"},{province:"hubei",city:"huanggang"}]}
8 ]);
删除文档 remove
1 db.userInfo.remove({ 条件查询});
2
3
相关推荐
好吃的肘子20 分钟前
MongoDB 应用实战
大数据·开发语言·数据库·算法·mongodb·全文检索
weixin_4723394629 分钟前
MySQL MCP 使用案例
数据库·mysql
lqlj22331 小时前
Spark SQL 读取 CSV 文件,并将数据写入 MySQL 数据库
数据库·sql·spark
独泪了无痕2 小时前
MongoTemplate 基础使用帮助手册
spring boot·mongodb
遗憾皆是温柔2 小时前
MyBatis—动态 SQL
java·数据库·ide·sql·mybatis
未来之窗软件服务2 小时前
Cacti 未经身份验证SQL注入漏洞
android·数据库·sql·服务器安全
fengye2071613 小时前
在MYSQL中导入cookbook.sql文件
数据库·mysql·adb
Ailovelearning3 小时前
neo4j框架:ubuntu系统中neo4j安装与使用教程
数据库·neo4j
_星辰大海乀4 小时前
表的设计、聚合函数
java·数据结构·数据库·sql·mysql·数据库开发
未来之窗软件服务5 小时前
solidwors插件 开发————仙盟创梦IDE
前端·javascript·数据库·ide·仙盟创梦ide