解决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 相关文章推荐
使用IPython来操作Docker容器的入门指引
Apr 08 Python
Linux中Python 环境软件包安装步骤
Mar 31 Python
Python进阶篇之字典操作总结
Nov 16 Python
Pycharm学习教程(1) 定制外观
May 02 Python
Python3.6实现连接mysql或mariadb的方法分析
May 18 Python
python 请求服务器的实现代码(http请求和https请求)
May 25 Python
Python Numpy计算各类距离的方法
Jul 05 Python
Python 网络编程之TCP客户端/服务端功能示例【基于socket套接字】
Oct 12 Python
python之array赋值技巧分享
Nov 28 Python
PyCharm无法引用自身项目解决方式
Feb 12 Python
10个示例带你掌握python中的元组
Nov 23 Python
baselines示例程序train_cartpole.py的ImportError
May 20 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
模板引擎Smarty深入浅出介绍
2006/12/06 PHP
php5.2 Json不能正确处理中文、GB编码的解决方法
2014/03/28 PHP
php实现mysql连接池效果实现代码
2018/01/25 PHP
Laravel中unique和exists验证规则的优化详解
2018/01/28 PHP
flash 得到自身url参数的代码
2009/11/15 Javascript
JavaScript 学习笔记二 字符串拼接
2010/03/28 Javascript
jQuery数据显示插件整合实现代码
2011/10/24 Javascript
jquery 插件学习(一)
2012/08/06 Javascript
javascript获取设置div的高度和宽度兼容任何浏览器
2013/09/22 Javascript
jquery全选checkBox功能实现代码(取消全选功能)
2013/12/10 Javascript
基于jquery的simpleValidate简易验证插件
2014/01/31 Javascript
使用JS或jQuery模拟鼠标点击a标签事件代码
2014/03/10 Javascript
jQuery自带的一些常用方法总结
2014/09/03 Javascript
当前流行的JavaScript代码风格指南
2014/09/10 Javascript
Javascript堆排序算法详解
2014/12/03 Javascript
JS动态修改表格cellPadding和cellSpacing的方法
2015/03/31 Javascript
javascript实现仿百度图片的瀑布流加载效果
2016/04/20 Javascript
Node.js开启Https的实践详解
2016/10/25 Javascript
微信小程序  audio音频播放详解及实例
2016/11/02 Javascript
Javascript继承机制详解
2017/05/30 Javascript
详解关闭令人抓狂的ESlint 语法检测配置方法
2019/10/28 Javascript
JS实现吸顶特效
2020/01/08 Javascript
原生js实现照片墙效果
2020/10/13 Javascript
微信小程序:报错(in promise) MiniProgramError
2020/10/30 Javascript
更改Python命令行交互提示符的方法
2015/01/14 Python
利用Django框架中select_related和prefetch_related函数对数据库查询优化
2015/04/01 Python
安装Python的教程-Windows
2017/07/22 Python
python爬虫实战之最简单的网页爬虫教程
2017/08/13 Python
大学生找工作推荐信范文
2013/11/28 职场文书
大学生创业感言
2014/01/25 职场文书
总会计师岗位职责
2014/02/19 职场文书
学员自我鉴定
2014/03/19 职场文书
新春联欢会主持词
2014/03/24 职场文书
三八红旗手事迹材料
2014/12/26 职场文书
初中团支书竞选稿
2015/11/21 职场文书
2016年万圣节活动个人总结
2016/04/05 职场文书