目录
4、 insertOne, inertMany, insert 的区别
1、基础认识
Mongo 是 humongous 的中间部分,在英文里是“巨大无比”的意思。所以 MongoDB 可以翻译成“巨大无比的数据库”,更优雅的叫法是“海量数据库”。
MongoDB是一款非关系型数据库,说到非关系型数据库,区别于关系型数据库最显著的特征就是没有SQL语句,数据没有固定的数据类型
2、特点
MongoDB是一个文档数据库(以 JSON 为数据模型),由C++语言编写,旨在为WEB应用提供可扩展的高性能数据存储解决方案。
它支持的数据结构非常松散,数据格式是BSON,一种类似JSON的二进制形式的存储格式,简称Binary JSON ,和JSON一样支持内嵌的文档对象和数组对象,因此可以存储比较复杂的数据类型。
Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。原则上 Oracle 和 MySQL 能做的事情,MongoDB 都能做(包括 ACID 事务)
3、MongoDB vs 关系型数据库
1、相似对比
数据库(database):最外层的概念,可以理解为逻辑上的名称空间,一个数据库包含多个不同名称的集合。
集合(collection):相当于SQL中的表,一个集合可以存放多个不同的文档。
文档(document):一个文档相当于数据表中的一行,由多个不同的字段组成。
字段(field):文档中的一个属性,等同于列(column)。
索引(index):独立的检索式数据结构,与SQL概念一致。
_id:每个文档中都拥有一个唯一的_id字段,相当于SQL中的主键(primary key)。
视图(view):可以看作一种虚拟的(非真实存在的)集合,与SQL中的视图类似。从MongoDB 3.4版本开始提供了视图功能,其通过聚合管道技术实现。
聚合操作($lookup):MongoDB用于实现“类似”表连接(tablejoin)的聚合操作符。
2、差异对比
1、半结构化
在一个集合中,文档所拥有的字段并不需要是相同的,而且也不需要对所用的字段进行声明。因此,MongoDB具有很明显的半结构化特点。除了松散的表结构,文档还可以支持多级的嵌套、数组等灵活的数据类型,非常契合面向对象的编程模型。
2、弱关系
MongoDB没有外键的约束,也没有非常强大的表连接能力。类似的功能需要使用聚合管道技术来弥补
3、MongoDB技术优势
基于灵活的JSON文档模型,非常适合敏捷式的快速开发。与此同时,其与生俱来的高可用、高水平扩展能力使得它在处理海量、高并发的数据应用时颇具优势
- SON 结构和对象模型接近,开发代码量低
- JSON的动态模型意味着更容易响应新的业务需求
- 复制集提供99.999%高可用
- 分片架构支持海量数据和无缝扩容
简单直观:从错综复杂的关系模型到一目了然的对象模型
4、MongoDB应用场景
- 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新;
- 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来;
- 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能;
- 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析;
- 视频直播,使用 MongoDB 存储用户信息、礼物信息等;
- 大数据应用,使用云数据库MongoDB作为大数据的云存储系统,随时进行数据提取分析,掌握行业动态。
只要有一项需求满足就可以考虑使用MongoDB,匹配越多,选择MongoDB越合适
4、MongoDB 安装
网址:Install MongoDB Community Kubernetes Operator | MongoDB
mongosh安装:
运行以下命令强制从社区仓库安装:
winget install MongoDB.mongosh --source winget
或直接指定官方发布:
winget install MongoDB.mongosh --source winget
5、基本操作
添加数据格式
3.2 版本之后新增了 db.collection.insertOne() 和 db.collection.insertMany()。
db.集合.insertOne(<JSON对象>) // 添加单个文档
db.集合.insertMany([{<JSON对象1>},{<JSON对象2>}]) // 批量添加文档
db.集合.insert() // 添加单个文档
1、插入文档
insertOne: 支持writeConcern
db.collection.insertOne(
<document>,
{
writeConcern: <document>
}
)
例如:
db.users.insertOne({name: "John", age: 30})
1、writeConcern
writeConcern 定义了本次文档创建操作的安全写级别。
高 writeConcern → 数据更安全,但延迟增加
低 writeConcern → 写入更快,但可能丢失数据
writeConcern 决定一个写操作落到多少个节点上才算成功。
writeConcern的取值包括:
值 |
含义 |
适用场景 |
---|---|---|
|
不等待确认,发完即视为成功(可能丢失数据) |
日志类低价值数据,追求最高写入速度 |
|
写入主节点内存即返回成功(默认值) |
单节点或副本集,平衡安全与性能 |
|
写入大多数节点才返回成功(强一致性) |
金融等高安全性场景 |
|
需写入至少 N 个节点(含主节点) |
自定义容灾级别 |
发起写操作的程序将阻塞到写操作到达指定的节点数为止
2、主键 _id
的生成规则
如果没有显示指定主键,MongoDB将默认创建一个主键,字段固定为_id,ObjectId() 可以快速生成的12字节id 作为主键,ObjectId 前四个字节代表了主键生成的时间,精确到秒。
主键ID在客户端驱动生成,一定程度上代表了顺序性,但不保证顺序性, 可以通过ObjectId("id值").getTimestamp() 获取创建时间。如:
ObjectId("5fe0ef13ac05741b758b3ced").getTimestamp();
3、inset和save区别
- insert: 若插入的数据主键已经存在,则会抛 DuplicateKeyException 异常,提示主键重复,不保存当前数据。
// 第一次插入(成功) db.products.insert({ _id: 100, name: "Phone", price: 599 }); // 第二次插入相同 _id(报错) db.products.insert({ _id: 100, name: "Laptop", price: 999 }); 输出错误: WriteError({ "code": 11000, "errmsg": "E11000 duplicate key error collection: test.products index: _id_ dup key: { _id: 100 }" })
- save: 如果 _id 主键存在则更新数据,如果不存在就插入数据。
// 第一次保存(插入新文档) db.products.save({ _id: 200, name: "Tablet", price: 299 }); // 第二次保存相同 _id(更新原有文档) db.products.save({ _id: 200, name: "Tablet Pro", price: 399 });
4、 insertOne, inertMany, insert 的区别
insertOne, 和 insertMany命令不支持 explain命令
insert支持 explain命令
2、批量新增文档
insertMany:向指定集合中插入多条文档数据
db.collection.insertMany(
[ <document 1> , <document 2>, ... ],
{
writeConcern: <document>,
ordered: <boolean>
}
)
writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。
ordered:指定是否按顺序写入,默认 true,按顺序写入。
顺序写入时,一旦遇到错误,便会退出,剩余的文档无论正确与否,都不会写入
乱序写入,则只要文档可以正确写入就会正确写入,不管前面的文档是否是错误的文档
- insert和save也可以实现批量插入
例子
MongoDB以集合(collection)的形式组织数据,collection 相当于关系型数据库中的表,如果collection不存在,当你对不存在的collection进行操作时,将会自动创建一个collection
如下:
将会创建一个 inventory 集合,并且插入 5 个文档
db.inventory.insertMany([
{ item: "journal", qty: 25, status: "A", size: { h: 14, w: 21, uom: "cm" }, tags: [ "blank", "red" ] },
{ item: "notebook", qty: 50, status: "A", size: { h: 8.5, w: 11, uom: "in" }, tags: [ "red", "blank" ] },
{ item: "paper", qty: 10, status: "D", size: { h: 8.5, w: 11, uom: "in" }, tags: [ "red", "blank", "plain" ] },
{ item: "planner", qty: 0, status: "D", size: { h: 22.85, w: 30, uom: "cm" }, tags: [ "blank", "red" ] },
{ item: "postcard", qty: 45, status: "A", size: { h: 10, w: 15.25, uom: "cm" }, tags: [ "blue" ] }
]);
3、查询
1、常用管理命令
查看服务器状态
db.serverStatus()
查看当前连接信息
db.runCommand({connectionStatus: 1})
退出 Shell
exit
2、数据库查询
show dbs
查看当前数据库的集合
show collections
3、文档查询
1、整个文档查询
查询所有的文档
db.inventory.find({})
返回格式化后的文档
db.inventory.find({}).pretty()
2、条件查询
1. 精准等值查询
db.inventory.find( { status: "D" } );
db.inventory.find( { qty: 0 } );
2. 多条件查询
db.inventory.find( { qty: 0, status: "D" } );
3. 嵌套对象精准查询
db.inventory.find( { "size.uom": "in" } );
4. 返回指定字段
默认会返回_id 字段, 同样可以通过指定 _id:0 ,不返回_id 字段
db.inventory.find( { }, { item: 1, status: 1 } );
5. 条件查询 and
db.inventory.find({$and:[{"qty":0},{"status":"A"}]}).pretty();
6. 条件查询 or
db.inventory.find({$or:[{"qty":0},{"status":"A"}]}).pretty();
Mongo查询条件和SQL查询对照表
(1)查询条件对照表
SQL |
MQL |
a = 1 |
{a: 1} |
a <> 1 |
{a: {$ne: 1}} |
a > 1 |
{a: {$gt: 1}} |
a >= 1 |
{a: {$gte: 1}} |
a < 1 |
{a: {$lt: 1}} |
a |
{a: {$lte: 1}} |
(2)查询逻辑对照表
SQL |
MQL |
a = 1 AND b = 1 |
{a: 1, b: 1}或{$and: [{a: 1}, {b: 1}]} |
a = 1 OR b = 1 |
{$or: [{a: 1}, {b: 1}]} |
a IS NULL |
{a: {$exists: false}} |
a IN (1, 2, 3) |
{a: {$in: [1, 2, 3]}} |
(3)查询逻辑运算符
- $lt: 存在并小于
- $lte: 存在并小于等于
- $gt: 存在并大于
- $gte: 存在并大于等于
- $ne: 不存在或存在但不等于
- $in: 存在并在指定数组中
- $nin: 不存在或不在指定数组中
- $or: 匹配两个或多个条件中的一个
- $and: 匹配全部条件