解决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 相关文章推荐
python实现登陆知乎获得个人收藏并保存为word文件
Mar 16 Python
Python 专题五 列表基础知识(二维list排序、获取下标和处理txt文本实例)
Mar 20 Python
python机器学习理论与实战(一)K近邻法
Jan 28 Python
在Pandas中DataFrame数据合并,连接(concat,merge,join)的实例
Jan 29 Python
Python 3.8中实现functools.cached_property功能
May 29 Python
python暴力解压rar加密文件过程详解
Jul 05 Python
Python3 chardet模块查看编码格式的例子
Aug 14 Python
详解使用python3.7配置开发钉钉群自定义机器人(2020年新版攻略)
Apr 01 Python
如何在VSCode下使用Jupyter的教程详解
Jul 13 Python
Python3如何实现Win10桌面自动切换
Aug 11 Python
使用OpenCV校准鱼眼镜头的方法
Nov 26 Python
利用python+request通过接口实现人员通行记录上传功能
Jan 13 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
计算2000年01月01日起到指定日的天数
2006/10/09 PHP
PHP XML操作的各种方法解析(比较详细)
2010/06/17 PHP
浅析php设计模式之数据对象映射模式
2016/03/03 PHP
PHP实现的文件操作类及文件下载功能示例
2016/12/24 PHP
PHP通过文件路径获取文件名的实例代码
2018/10/14 PHP
为Plesk PHP7启用Oracle OCI8扩展方法总结
2019/03/29 PHP
jQuery 连续列表实现代码
2009/12/21 Javascript
在百度知道团队中快速审批新成员的js脚本
2014/02/02 Javascript
JavaScript新窗口与子窗口传值详解
2014/02/11 Javascript
网页广告中JS代码的信息监听示例
2014/04/02 Javascript
详解JavaScript的另类写法
2016/04/11 Javascript
BootStrap的alert提示框的关闭后再显示怎么解决
2016/05/17 Javascript
微信小程序 弹窗自定义实例代码
2017/03/08 Javascript
easyui关于validatebox实现多重规则验证的方法(必看)
2017/04/12 Javascript
微信小程序实战之仿android fragment可滑动底部导航栏(4)
2020/04/16 Javascript
详解如何在NodeJS项目中优雅的使用ES6
2017/04/22 NodeJs
javascript  删除select中的所有option的实例
2017/09/17 Javascript
webpack4 css打包压缩问题的解决
2018/05/18 Javascript
vue-router 实现导航守卫(路由卫士)的实例代码
2018/09/02 Javascript
Vue-Cli项目优化操作的实现
2019/10/27 Javascript
在vue中封装的弹窗组件使用队列模式实现方法
2020/07/23 Javascript
Python实现的选择排序算法原理与用法实例分析
2017/11/22 Python
Python中pillow知识点学习
2018/04/30 Python
代码实例讲解python3的编码问题
2019/07/08 Python
Python tkinter布局与按钮间距设置方式
2020/03/04 Python
Python3 利用face_recognition实现人脸识别的方法
2020/03/13 Python
python对XML文件的操作实现代码
2020/03/27 Python
Optimalprint加拿大:在线打印服务
2020/04/03 全球购物
出国留学介绍信
2014/01/13 职场文书
2014党员民主评议个人总结
2014/09/10 职场文书
全国法制宣传日活动总结
2015/05/05 职场文书
幼儿园教师个人工作总结2015
2015/05/12 职场文书
退税申请报告怎么写
2015/05/18 职场文书
Java Socket实现Redis客户端的详细说明
2021/05/26 Redis
Python&Matlab实现樱花的绘制
2022/04/07 Python
python playwrigh框架入门安装使用
2022/07/23 Python