解决Pymongo insert时会自动添加_id的问题


Posted in Python onDecember 05, 2020

在使用pymongo时遇到了一个小坑:

在Flask框架中,将字典插入mongodb后再返回就报错

@app.route('xxxx')
def main():
 ...
 data = {
 'a':'a',
 'b':'b'
 }
 mycol.insert_one(data)
 return data
Traceback (most recent call last):
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/app.py", line 2464, in __call__
 return self.wsgi_app(environ, start_response)
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/app.py", line 2450, in wsgi_app
 response = self.handle_exception(e)
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/app.py", line 1867, in handle_exception
 reraise(exc_type, exc_value, tb)
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
 raise value
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/app.py", line 2447, in wsgi_app
 response = self.full_dispatch_request()
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/app.py", line 1953, in full_dispatch_request
 return self.finalize_request(rv)
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/app.py", line 1968, in finalize_request
 response = self.make_response(rv)
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/app.py", line 2112, in make_response
 rv = jsonify(rv)
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/json/__init__.py", line 370, in jsonify
 dumps(data, indent=indent, separators=separators) + "\n",
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/json/__init__.py", line 211, in dumps
 rv = _json.dumps(obj, **kwargs)
 File "/home/xiang/.local/lib/python3.6/site-packages/simplejson/__init__.py", line 412, in dumps
 **kw).encode(obj)
 File "/home/xiang/.local/lib/python3.6/site-packages/simplejson/encoder.py", line 298, in encode
 chunks = list(chunks)
 File "/home/xiang/.local/lib/python3.6/site-packages/simplejson/encoder.py", line 696, in _iterencode
 for chunk in _iterencode_dict(o, _current_indent_level):
 File "/home/xiang/.local/lib/python3.6/site-packages/simplejson/encoder.py", line 652, in _iterencode_dict
 for chunk in chunks:
 File "/home/xiang/.local/lib/python3.6/site-packages/simplejson/encoder.py", line 716, in _iterencode
 o = _default(o)
 File "/home/xiang/.local/lib/python3.6/site-packages/flask/json/__init__.py", line 100, in default
 return _json.JSONEncoder.default(self, o)
 File "/home/xiang/.local/lib/python3.6/site-packages/simplejson/encoder.py", line 273, in default
 o.__class__.__name__)
TypeError: Object of type ObjectId is not JSON serializable

这是由于pymongo在进行插入操作时,如果字典中没有‘_id',会自动添加‘_id',而它的值为ObjectId实例,flask在对返回值进行编码时无法编码ObjectId类型实例,所以报错,解决办法就是去掉‘_id'或者mycol.insert_one(data.copy())

解决Pymongo insert时会自动添加_id的问题

补充知识:pymongo去重: 插入数据时,不存在则插入,存在则不执行

爬虫想把爬取的数据存入到mongoDB中, 这时候经常遇到的一个需求就是插入的数据已经存在数据库中, 因此插入前去重就是一个经常性的课题.

我的想法是:

如果数据库中已经存在这个数据, 那么就什么也不操作

如果数据不存在, 则插入这个数据

为了实现这个想法, 查了很多文献, 发现使用update 可以实现

下面就是我测试的代码

# 首先在数据中插入一条数据
document = {
  'p_id': 'f75046d73a0c4bf88f0b7342e60722c4',
  'c_name': 'Ken',
  'c_star': '5.0',
  'bought': None,
  'c_time': '2017年3月23日',
  'c_userful': 13,
  'c_comment': ['4?rになるトイプ?ドル用に?入。', '今までエサは床に食器直置きで与えていましたが、食後にむせていることがたびたび目?膜丹欷郡韦?, '「もしかして食べづらいのでは?」と思い?べてみたところ、この商品にたどり着きました。', '足が?いので食事中は?が完全に下に向いており、胃や足腰に?担がかかっていたと思われます。'],
  'gmt_create': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
}
collection.insert(document)

通过mongoDB可视化工具查看数据库,发现数据已经存在

解决Pymongo insert时会自动添加_id的问题

要实现如果不存在就插入,如果存在就不插入的要求,我们需要用到 update的一个参数:‘$setOnInsert'

$setOnInsert官方文档点击查看

通过阅读官方文档我们可以发现 与$setOnInsert方法想配合的最重要的参数就是 upsert:True

update源码中的upsert参数默认为False,只需要将update方法的upsert参数修改为True是否就能达到需要的效果呢?

现在我们执行相同数据的插入看看效果

# 首先需要限定一个重复的条件,比如我们想除了gmt_create参数以外,全部不一样就算不重复, 先限定一个条件
result_find = {
  'p_id': 'f75046d73a0c4bf88f0b7342e60722c4',
  'c_name': 'Ken',
  'c_star': '5.0',
  'bought': None,
  'c_time': '2017年3月23日',
  'c_userful': 13,
  'c_comment': ['4?rになるトイプ?ドル用に?入。', '今までエサは床に食器直置きで与えていましたが、食後にむせていることがたびたび目?膜丹欷郡韦?,
         '「もしかして食べづらいのでは?」と思い?べてみたところ、この商品にたどり着きました。', '足が?いので食事中は?が完全に下に向いており、胃や足腰に?担がかかっていたと思われます。']
}
# 执行 update
collection.update(
  result_find,
  {'$setOnInsert': document},
  upsert=True
)

执行完之后, 去数据库中查看,发现还是原来的那条数据, 并没有多出一条来, 说明可以实现 如果存在就不操作的要求

那么能实现 如果不存在就插入的要求吗?

我们去数据库可视化工具中 把数据库中的数据删除, 然后执行下面操作

document = {
  'p_id': 'f75046d73a0c4bf88f0b7342e60722c4',
  'c_name': 'Ken',
  'c_star': '5.0',
  'bought': None,
  'c_time': '2017年3月23日',
  'c_userful': 13,
  'c_comment': ['4?rになるトイプ?ドル用に?入。', '今までエサは床に食器直置きで与えていましたが、食後にむせていることがたびたび目?膜丹欷郡韦?, '「もしかして食べづらいのでは?」と思い?べてみたところ、この商品にたどり着きました。', '足が?いので食事中は?が完全に下に向いており、胃や足腰に?担がかかっていたと思われます。'],
  'gmt_create': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
}

result_find = {
  'p_id': 'f75046d73a0c4bf88f0b7342e60722c4',
  'c_name': 'Ken',
  'c_star': '5.0',
  'bought': None,
  'c_time': '2017年3月23日',
  'c_userful': 13,
  'c_comment': ['4?rになるトイプ?ドル用に?入。', '今までエサは床に食器直置きで与えていましたが、食後にむせていることがたびたび目?膜丹欷郡韦?,
         '「もしかして食べづらいのでは?」と思い?べてみたところ、この商品にたどり着きました。', '足が?いので食事中は?が完全に下に向いており、胃や足腰に?担がかかっていたと思われます。']
}

# collection.insert(document)
collection.update(
  result_find,
  {'$setOnInsert': document},
  upsert=True
)

然后我们发现数据中出现了我们想看到的这条数据

所以, 实现了我们的要求: 存在则不操作, 不存在则插入.

以上这篇解决Pymongo insert时会自动添加_id的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Django中实现一个高性能计数器(Counter)实例
Jul 09 Python
数据挖掘之Apriori算法详解和Python实现代码分享
Nov 07 Python
在Python中使用全局日志时需要注意的问题
May 06 Python
简单谈谈Python中的闭包
Nov 30 Python
python抓取京东小米8手机配置信息
Nov 13 Python
Python3爬虫学习之将爬取的信息保存到本地的方法详解
Dec 12 Python
解决python线程卡死的问题
Feb 18 Python
在python中实现调用可执行文件.exe的3种方法
Jul 07 Python
Python装饰器使用你可能不知道的几种姿势
Oct 25 Python
Python ORM编程基础示例
Feb 02 Python
Python文件操作模拟用户登陆代码实例
Jun 09 Python
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
Mar 29 Python
用python对oracle进行简单性能测试
Dec 05 #Python
python mongo 向数据中的数组类型新增数据操作
Dec 05 #Python
python自动从arxiv下载paper的示例代码
Dec 05 #Python
python使用dlib进行人脸检测和关键点的示例
Dec 05 #Python
python从ftp获取文件并下载到本地
Dec 05 #Python
python基于socket模拟实现ssh远程执行命令
Dec 05 #Python
Python实现PS滤镜中的USM锐化效果
Dec 04 #Python
You might like
php4的session功能评述(三)
2006/10/09 PHP
安装APACHE
2007/01/15 PHP
深入PHP empty(),isset(),is_null()的实例测试详解
2013/06/06 PHP
php不使用插件导出excel的简单方法
2014/03/04 PHP
win7安装php框架Yii的方法
2016/01/25 PHP
php实现多站点共用session实现单点登录的方法详解
2019/09/18 PHP
TextArea设置MaxLength属性最大输入值的js代码
2012/12/21 Javascript
JavaScript数组常用操作技巧汇总
2014/11/17 Javascript
JavaScript异步加载浅析
2014/12/28 Javascript
js如何打印object对象
2015/10/16 Javascript
js运动事件函数详解
2016/10/21 Javascript
JS中静态页面实现微信分享功能
2017/02/06 Javascript
VUE中v-model和v-for指令详解
2017/06/23 Javascript
JS实现简单表格排序操作示例
2017/10/07 Javascript
iview table高度动态设置方法
2018/03/14 Javascript
原生JS进行前后端同构
2018/04/22 Javascript
原生JS实现旋转轮播图+文字内容切换效果【附源码】
2018/09/29 Javascript
JS/CSS实现字符串单词首字母大写功能
2019/09/03 Javascript
JS桶排序的简单理解与实现方法示例
2019/11/25 Javascript
js中的面向对象之对象常见创建方法详解
2019/12/16 Javascript
基于JavaScript实现留言板功能
2020/03/16 Javascript
分析Python编程时利用wxPython来支持多线程的方法
2015/04/07 Python
在Python中操作字典之update()方法的使用
2015/05/22 Python
实例解析Python设计模式编程之桥接模式的运用
2016/03/02 Python
python使用pil库实现图片合成实例代码
2018/01/20 Python
对python 命令的-u参数详解
2018/12/03 Python
Django利用cookie保存用户登录信息的简单实现方法
2019/05/27 Python
Araks官网:纽约内衣品牌
2020/10/15 全球购物
办公室副主任岗位职责
2013/11/25 职场文书
英文自荐信格式
2013/11/28 职场文书
求职简历自我评价范例
2014/03/12 职场文书
合作投资意向书
2014/04/01 职场文书
2015年会计个人工作总结
2015/04/02 职场文书
Python批量将csv文件转化成xml文件的实例
2021/05/10 Python
Python安装及建立虚拟环境的完整步骤
2022/06/25 Servers
CSS浮动引起的高度塌陷问题
2022/08/05 HTML / CSS