谈谈Mongodb insertMany的一些坑

概述

Mongodb提供了多种方法向集合中插入数据

  • 插入一条数据
db.collection.insertOne()
  • 插入多个文档
db.collection.insertMany()
  • 更新集合中不存在的文档数据,指定{upsert: true}时插入数据
db.collection.updateOne()
db.collection.updateMany()
db.collection.findAndModify()
db.collection.findAndUpdate()
db.collection.findAndReplace()
db.collection.bulkWrite()

_id字段

mongodb插入方法中,对_id字段有一致的行为。当客户端插入数据,没有指定_id字段时,数据库自动添加一个ObjectId类型的_id字段作为主键。mongodb为集合的_id字段添加唯一键索引,因此用户插入带有_id字段的文档时,mongodb会对_id字段唯一性进行校验。数据成功插入后,mongodb返回插入文档的id

//向集合product插入一条没有id字段的文档
db.products.insertOne( { item: "card", qty: 15})//返回插入成功并返回插入数据的id
{"acknowledged" : true,"insertedId" : ObjectId("65966778d63bea6fd2f4b7a7")
}//向集合product插入指定id字段的文档
db.products.insertMany([{_id:1, item: "card", qty: 15},{_id:2, item: "pen", qty: 15},
] )//返回插入成功和插入数据的id
{"acknowledged" : true,"insertedIds" : [ 1, 2 ]
}//向集合products插入已存_id的数据
db.products.insertMany([{_id:2, item: "bag", qty: 15}
] )//报错
"writeErrors" : [{"index" : 0,"code" : 11000,"errmsg" : "E11000 duplicate key error collection: test.products index: _id_ dup key: { _id: 2 }","op" : {"_id" : 2,"item" : "bag","qty" : 15}}],

原子性

Mongodb对单文档的操作是原子性的。包括单文档的插入更新和删除操作。而插入方法中的insertMany(), updateMany(),bulkWrite()方法,操作多个文档的时,并不是原子操作。这样会产生一个问题,执行insertMany()方法,倒地插入了多少条数据。

//这条语句,插入多少条数据?
db.products.insertMany([{_id:3, item: "bag", qty: 15},{_id:4, item: "ruler", qty: 10},{_id:4, item: "cup", qty: 12},{_id:5, item: "key", qty: 14}
] )

回顾insertMany的语法

//insertMany的语法
db.collection.insertMany([<document 1>, <document 2>, ...],{writeConcern: <document>,ordered:<boolean>}
)

参数定义

参数名

类型

描述

document

文档类型

计划插入的文档数组

writeConcern

文档类型

可选参数,指定数据提交方式,缺省使用默认数据提交方式

ordered

布尔类型

是否按照数组中文档的顺序插入数据,默认true

这里writeConcern参数稍后再提,ordered参数,会对报错的insertMany()方法结果产生不同的影响。当指定ordered为true或使用默认值时。Mongodb按照数组中文档的顺序,逐一将数据插入集合。插入过程中出现错误时,插入操作停止,后面的数据不会被插入。当指定ordered为false时,数据插入过程中出错时,mongodb会继续插入后面的数据。

db.products.insertMany([{_id:3, item: "bag", qty: 15},{_id:4, item: "ruler", qty: 10},{_id:4, item: "cup", qty: 12},{_id:5, item: "key", qty: 14}
] )BulkWriteError({"writeErrors" : [{"index" : 2,"code" : 11000,"errmsg" : "E11000 duplicate key error collection: test.products index: _id_ dup key: { _id: 4 }","op" : {"_id" : 4,"item" : "cup","qty" : 12}}],"writeConcernErrors" : [ ],"nInserted" : 2,"nUpserted" : 0,"nMatched" : 0,"nModified" : 0,"nRemoved" : 0,"upserted" : [ ]
})

返回结果中,显示插入2条数据,其中item: "cup"的数据,因为主键冲突插入失败,而_id:5的数据,也没有插入

指定{ordered: false},重新执行插入

db.products.insertMany([{_id:3, item: "bag", qty: 15},{_id:4, item: "ruler", qty: 10},{_id:4, item: "cup", qty: 12},{_id:5, item: "key", qty: 14}
], {ordered: false
} )BulkWriteError({"writeErrors" : [{"index" : 2,"code" : 11000,"errmsg" : "E11000 duplicate key error collection: test.products index: _id_ dup key: { _id: 4 }","op" : {"_id" : 4,"item" : "cup","qty" : 12}}],"writeConcernErrors" : [ ],"nInserted" : 3,"nUpserted" : 0,"nMatched" : 0,"nModified" : 0,"nRemoved" : 0,"upserted" : [ ]
})

3条数据插入成功,只有item: "cup" 因为主键冲突,导致插入失败

这里没有使用mongodb的事务。mongodb的事务是原子性的,当在mongodb事务中插入数据报错时,数据都不会被插入。

writeConcern

现在来探讨一下writeConcern。 mongodb通过writeConcern定义了复制集中数据提交返回的方法。当指定writeConcern为majority时,需要大于一般的复制集节点数据提交完成通知主节点后,主节点才会将插入结果返回给客户端。如果从节点通知主节点的时间超过了wtimeout设定的时间,数据插入时会报replication time out error。

//本案例可能无法再本地重现,适当减少wtimeout时间尝试
db.products.insertMany([{ _id: 10, item: "large box", qty: 20 },{ _id: 11, item: "small box", qty: 55 },{ _id: 12, item: "medium box", qty: 30 }],{ w: "majority", wtimeout: 100 });WriteConcernError({"code" : 64,"errmsg" : "waiting for replication timed out","errInfo" : {"wtimeout" : true,"writeConcern" : {    // Added in MongoDB 4.4"w" : "majority","wtimeout" : 100,"provenance" : "getLastErrorDefaults"}}
})

插入数量

每次插入操作插入文档的数量,不能超过maxWriteBatchSize的限制。maxWriteBatchSize默认值是100000. 设置这样的限制,避免了数据库插入超量报错。一些数据库连接驱动插入数据时,会按照maxWriteBatchSize将插入数据分批插入。如插入200000条数据,数据库驱动可能会分成两个插入操作,每次插入100000条。

执行计划

insertOne(), insertMany()方法不支持使用db.collection.explain()方法获取执行计划。

性能

向数据库插入大量随机数字段(如hash值),并在这些字段上有索引时,插入性能可能会变差。批量插入随机数时,构建更新索引会消耗大量的cpu和内存。因此插入这样的数据时,建议预先删除集合上的索引,插入完成后重新构建索引。或向一个没有索引的集合插入数据。

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

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

相关文章

Go语言之父:开源14年,Go不止是编程语言,究竟做对了哪些?

提及编程语言&#xff0c;2023 年&#xff0c;除了老牌的 C 和新晋之秀 Rust 热度最高之外&#xff0c;就要数 Go 了。 从 2009 年由 C 语言获取灵感而发布&#xff0c;到如今风靡已久的高性能语言&#xff0c;Go 已经走过了 14 个年头。 “Go是一个项目&#xff0c;不只是一门…

基于ssm的智慧社区电子商务系统+vue论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

Go语言中的init函数的执行时机

init函数的执行时机 这个涉及到 init 函数的作用和执行顺序相同个文件和不同文件中以及在不同的包中init的执行顺序go文件初始化的顺序 一、init 函数的作用和执行顺序 作用 init 函数是用于程序执行前做包的初始化的函数&#xff0c;比如初始化包里面的一些变量等等通常在…

HTML5大作业-精致版个人博客空间模板源码

文章目录 1.设计来源1.1 博客主页界面1.2 博主信息界面1.3 我的文章界面1.4 我的相册界面1.5 我的工具界面1.6 我的源码界面1.7 我的日记界面1.8 我的留言板界面1.9 联系博主界面 2.演示效果和结构及源码2.1 效果演示2.2 目录结构2.3 源代码 源码下载 作者&#xff1a;xcLeigh …

从零学Java 包装类

Java 包装类 文章目录 Java 包装类1 什么是包装类?2 为什么需要包装类?3 包装类对应4 包装类的基本操作4.1 装箱4.2 拆箱4.3 自动装箱/拆箱面试题整数缓冲区 5 包装类的类型转换5.1 字符串转基本数据类型5.2 基本数据类型转字符串5.2.1 方法一: 号字符串拼接5.2.2 方法二: 使…

在MS中基于perl脚本实现氢键统计

氢原子与电负性大的原子X以共价键结合&#xff0c;若与电负性大、半径小的原子Y&#xff08;O F N等&#xff09;接近&#xff0c;在X与Y之间以氢为媒介&#xff0c;生成X-H…Y形式的一种特殊的分子间或分子内相互作用&#xff0c;称为氢键。 氢键通常是物质在液态时形成的&…

【华为OD真题 Python】解密犯罪时间

文章目录 题目描述输入描述输出描述示例1输入输出说明示例1输入输出说明示例2输入输出说明备注代码实现题目描述 警察在侦破一个案件时,得到了线人给出的可能

第1章 线性回归

一、基本概念 1、线性模型 2、线性模型可以看成&#xff1a;单层的神经网络 输入维度&#xff1a;d 输出维度&#xff1a;1 每个箭头代表权重 一个输入层&#xff0c;一个输出层 单层神经网络&#xff1a;带权重的层为1&#xff08;将权重和输入层放在一起&#xff09; 3、…

数据库设计——DML

D M L \huge{DML} DML DML&#xff1a;数据库操作语言&#xff0c;用来对数据库中的数据进行增删改查。 增&#xff08;INSERT&#xff09; 使用insert来向数据库中增加数据。 示例&#xff1a; -- DML : 数据操作语言 -- DML : 插入数据 - insert -- 1. 为 tb_emp 表的 us…

Kubernetes二进制部署 单节点

一、环境准备 k8s集群master1&#xff1a;192.168.229.90 kube-apiserver kube-controller-manager kube-scheduler etcd k8s集群node1: 192.168.229.80 kubelet kube-proxy docker flannel k8s集群node2: 192.168.229.70 kubelet kube-proxy docker flannel 至少2C2G 常见的k…

Flutter3.X基础入门教程(2024完整版)

Flutter介绍&#xff1a; Flutter是谷歌公司开发的一款开源、免费的UI框架&#xff0c;可以让我们快速的在Android和iOS上构建高质量App。它最大的特点就是跨平台、以及高性能。 目前Flutter已经支持 iOS、Android、Web、Windows、macOS、Linux的跨平台开发。 教程所讲内容支持…

独立式键盘控制步进电机实验

#include<reg51.h> //包含51单片机寄存器定义的头文件 sbit S1P1^4; //将S1位定义为P1.4引脚 sbit S2P1^5; //将S2位定义为P1.5引脚 sbit S3P1^6; //将S3位定义为P1.6引脚 unsigned char keyval; //储存按键值 unsigned char ID; …

bat批处理文件_命令汇总(2)

文章目录 1、换行2、返回上一级目录cd..3、隐藏指令回显echo off4、开启指令回显echo on5、用关闭echo off指令本身的回显6、echo提示信息 1、换行 cd.. echo. echo. echo. pause2、返回上一级目录cd… 3、隐藏指令回显echo off echo off echo hello1 echo hello2 pause4、开…

tomcat session cookie值设置逻辑

tomcat session cookie 值设置&#xff0c;tomcat jsessionid设置 ##调用request.getSession() Controller RequestMapping("/cookie") public class CookieController {RequestMapping("/tomcatRequest")ResponseBodypublic String tomcatRequest(HttpS…

软件测试|什么是Python构造方法,构造方法如何使用?

构造方法&#xff08;Constructor&#xff09;是面向对象编程中的重要概念&#xff0c;它在创建对象时用于初始化对象的实例变量。在Python中&#xff0c;构造方法是通过特殊的名称__init__()来定义的。本文将介绍Python构造方法的基本概念、语法和用法。 什么是构造方法&…

轻松获取CHATGPT API:免费、无验证、带实例

免费获取和使用ChatGPT API的方法 快速开始&#xff1a;视频教程 章节一&#xff1a;GPT-API-Free开源项目介绍 GPT-API-Free 是一个开源项目&#xff0c;它提供了一个中转API KEY&#xff0c;使用户能够调用多个GPT模型&#xff0c;包括gpt-3.5-turbo、embedding和gpt-4。这…

记一次服务器被入侵的排查过程

起因 阿里云安全中心报告了告警信息&#xff0c;同时手机短信、邮件、电话也接收到了来自阿里云的风险通知&#xff0c;感觉这方面阿里云还是不错。 排查及解决过程 这条wget指令究竟是怎么被运行的 我无法定位到攻击人员是通过什么样的方式让我的java程序执行了wget这条指…

JavaScript中绑定事件的方法

在JavaScript中&#xff0c;绑定事件的方法主要有三种&#xff1a; 直接在HTML元素中通过onclick&#xff0c;onload等属性直接绑定事件处理函数。使用DOM0级事件绑定&#xff0c;即直接在JavaScript代码中通过element.onclick function()或者element.addEventListener(click…

地平面--高速布线

https://baijiahao.baidu.com/s?id1764139038516816855&wfrspider&forpc 概念 回顾传输线&#xff0c;由任意两条有一定长度的导线组成&#xff0c;一条为信号路径&#xff0c;一条为返回路径。基本电路理论告诉我们&#xff0c;信号是由电流传播的&#xff0c;明确的…

ECMAScript简介及特性

ECMAScript&#xff0c;通常简称为ES&#xff0c;是一种由ECMA&#xff08;欧洲计算机协会&#xff09;国际组织标准化和推动的脚本语言规范。它被广泛用于Web浏览器和服务器端编程&#xff0c;是JavaScript的基础。 ECMAScript的起源可以追溯到1996年&#xff0c;当时Netscape…