mongo insert_many BulkWriteError

本文探讨了使用pymongo在MongoDB中批量插入数据时遇到的BulkWriteError错误,并通过实例说明了当尝试插入相同的文档引用时如何复现该问题。

问题:

在对mongo插入数据时,报写入问题,报错信息如下:

Traceback (most recent call last):
  File "/root/crs/call_history_crawler/worker/communicate.py", line 149, in insert_db_data
    if db[table].insert_many(data):
  File "/root/crs/call_history_crawler/venv/lib/python2.7/site-packages/pymongo/collection.py", line 684, in insert_many
    blk.execute(self.write_concern.document)
  File "/root/crs/call_history_crawler/venv/lib/python2.7/site-packages/pymongo/bulk.py", line 470, in execute
    return self.execute_command(sock_info, generator, write_concern)
  File "/root/crs/call_history_crawler/venv/lib/python2.7/site-packages/pymongo/bulk.py", line 314, in execute_command
    raise BulkWriteError(full_result)
BulkWriteError: batch op errors occurred

分析

问题出现在,对同一文本进行多次插入,官方说法:insert_many() with a list of references to a single document raises BulkWriteError

>>> doc = {}
>>> collection.insert_many(doc for _ in range(10))
Traceback (most recent call last):
...
pymongo.errors.BulkWriteError: batch op errors occurred
>>> doc
{'_id': ObjectId('560f171cfba52279f0b0da0c')}

>>> docs = [{}]
>>> collection.insert_many(docs * 10)
Traceback (most recent call last):
...
pymongo.errors.BulkWriteError: batch op errors occurred
>>> docs
[{'_id': ObjectId('560f1933fba52279f0b0da0e')}]

作者:Chihwei_hsu
来源:http://chihweihsu.com
Github:https://github.com/HsuChihwei


<think>我们逐行解释这段代码,该代码用于创建MongoDB的异步客户端连接并获取数据库实例。 注意:这里使用了motor.motor_asyncio.AsyncIOMotorClient来创建异步客户端。 代码中使用了settings对象,这通常是一个配置对象,包含了MongoDB连接所需的各种参数。 具体解释如下: </think> 以下是对代码的逐行详细解释: ```python # 创建 MongoDB 异步客户端连接实例 self.mongo_client = AsyncIOMotorClient( # MongoDB 连接字符串(包含主机、端口、认证信息等) settings.MONGO_URI, # 连接池最大连接数(从配置中获取) maxPoolSize=settings.MONGO_MAX_CONNECTIONS, # 连接池最小保持连接数(从配置中获取) minPoolSize=settings.MONGO_MIN_CONNECTIONS, # 连接最大空闲时间(毫秒),30秒后空闲连接将被关闭 maxIdleTimeMS=30000, # 30秒空闲超时 # 服务器选择超时时间(毫秒),从配置获取 serverSelectionTimeoutMS=settings.MONGO_SERVER_SELECTION_TIMEOUT_MS, # 服务器选择超时 # 连接建立超时时间(毫秒),从配置获取 connectTimeoutMS=settings.MONGO_CONNECT_TIMEOUT_MS, # 连接超时 # 套接字操作超时时间(毫秒),从配置获取 socketTimeoutMS=settings.MONGO_SOCKET_TIMEOUT_MS, # 套接字超时 ) # 从客户端连接获取指定名称的数据库实例 self.mongo_db = self.mongo_client[settings.MONGO_DB] ``` ### 详细解释: 1. **AsyncIOMotorClient 实例化**: - 创建 MongoDB 的异步客户端连接对象 - 使用多个参数优化连接行为 2. **连接参数详解**: | 参数 | 类型 | 说明 | 典型值 | |------|------|------|--------| | `settings.MONGO_URI` | str | MongoDB 连接字符串 | `"mongodb://user:pass@host:port"` | | `maxPoolSize` | int | 连接池最大连接数 | 100 | | `minPoolSize` | int | 连接池最小空闲连接数 | 5 | | `maxIdleTimeMS` | int | 连接最大空闲时间(毫秒) | 30000 (30秒) | | `serverSelectionTimeoutMS` | int | 选择可用服务器超时时间 | 30000 (30秒) | | `connectTimeoutMS` | int | TCP连接建立超时时间 | 10000 (10秒) | | `socketTimeoutMS` | int | 套接字操作(I/O)超时时间 | 60000 (60秒) | 3. **数据库实例获取**: - `self.mongo_client[settings.MONGO_DB]`:通过客户端对象访问特定数据库 - 使用方括号语法(字典样式)选择数据库 - `settings.MONGO_DB`:从配置中获取数据库名称 ### 连接池工作原理: ```mermaid graph LR A[应用程序] --> B[连接池] B -->|获取连接| C[DB Server 1] B -->|获取连接| D[DB Server 2] B -->|空闲超时| E[释放连接] style B fill:#cff,stroke:#333 ``` ### 最佳实践说明: 1. **连接池配置**: - `maxPoolSize` 应根据应用负载设置 - `minPoolSize` 减少连接建立开销 - `maxIdleTimeMS` 防止空闲连接占用资源 2. **超时设置**: - `serverSelectionTimeoutMS`:集群环境下选择可用节点的时间 - `connectTimeoutMS`:TCP 三次握手超时 - `socketTimeoutMS`:查询/操作执行超时 3. **异步特性**: - 所有 I/O 操作非阻塞 - 适合异步框架(FastAPI,Tornado 等) - 使用 `await` 执行数据库操作 ### 完整使用示例: ```python async def get_user_data(user_id: str): # 使用连接池中的连接执行查询 user = await self.mongo_db.users.find_one({"_id": user_id}) return user # 在异步上下文中调用 async def main(): await initialize_db() # 初始化连接 user = await get_user_data("12345") print(user) ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值