解决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 pickle 和 shelve模块的用法
Sep 16 Python
python 线程的暂停, 恢复, 退出详解及实例
Dec 06 Python
python3 判断列表是一个空列表的方法
May 04 Python
python实现决策树分类(2)
Aug 30 Python
Python中常用的内置方法
Jan 28 Python
python3 深浅copy对比详解
Aug 12 Python
python通过opencv实现图片裁剪原理解析
Jan 19 Python
Pandas把dataframe或series转换成list的方法
Jun 14 Python
pycharm 2020 1.1的安装流程
Sep 29 Python
pytorch中index_select()的用法详解
Jan 06 Python
pycharm 实现调试窗口恢复
Feb 05 Python
Python中os模块的简单使用及重命名操作
Apr 17 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
一个php Mysql类 可以参考学习熟悉下
2009/06/21 PHP
ajax完美实现两个网页 分页功能的实例代码
2013/04/16 PHP
如何正确配置Nginx + PHP
2016/07/15 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
prototype1.4中文手册
2006/09/22 Javascript
JavaScript动态创建link标签到head里的方法
2014/12/22 Javascript
javascript手风琴下拉菜单实现代码
2015/11/12 Javascript
基于slideout.js实现移动端侧边栏滑动特效
2016/11/28 Javascript
js判断用户是输入的地址请求的路径(实例讲解)
2017/07/18 Javascript
node.js遍历目录的方法示例
2018/08/01 Javascript
vue3.0 CLI - 2.3 - 组件 home.vue 中学习指令和绑定
2018/09/14 Javascript
vue项目首屏打开速度慢的解决方法
2019/03/31 Javascript
layui关闭层级、简单监听的实例
2019/09/06 Javascript
javascript网页随机点名实现过程解析
2019/10/15 Javascript
vue实现选中效果
2020/10/07 Javascript
[04:15]DOTA2-DPC中国联赛1月19日Recap集锦
2021/03/11 DOTA
详解Python操作RabbitMQ服务器消息队列的远程结果返回
2016/06/30 Python
Python语言生成水仙花数代码示例
2017/12/18 Python
详解python中自定义超时异常的几种方法
2019/07/29 Python
python lambda函数及三个常用的高阶函数
2020/02/05 Python
python继承threading.Thread实现有返回值的子类实例
2020/05/02 Python
Python通过类的组合模拟街道红绿灯
2020/09/16 Python
python 模拟登录B站的示例代码
2020/12/15 Python
PyCharm 光标变成黑块的解决方式
2021/02/06 Python
Oakley西班牙官方商店:太阳眼镜和男女运动服
2019/04/26 全球购物
俄罗斯香水在线商店:AromaCode
2019/12/04 全球购物
.NET现在共支持多少种语言
2014/02/26 面试题
管理科学大学生求职信
2013/11/13 职场文书
技术总监个人的自我评价范文
2013/12/18 职场文书
行政部主管岗位职责
2013/12/28 职场文书
求职自我推荐信
2015/03/24 职场文书
学校党支部公开承诺书
2015/04/30 职场文书
再读《皇帝的新衣》的读后感悟!
2019/08/07 职场文书
PyTorch dropout设置训练和测试模式的实现
2021/05/27 Python
解决flex布局中子项目尺寸不受flex-shrink限制
2022/05/11 HTML / CSS
详解Golang如何实现支持随机删除元素的堆
2022/09/23 Python