如何在pymongo的delete_many()方法中正确使用hint参数?
pymongo中delete_many使用hint参数的错误原因与解决方案
错误原因说明
- 第一个
TypeError报错是pymongo的语法限制:hint参数要求传入有序结构,字典属于无序结构所以不被支持,你后续修改为元组列表的操作是正确的。 - 第二个
pymongo.errors.OperationFailure: BSON field 'delete.deletes.hint' is an unknown field.报错是核心问题:pymongo 3.11+仅代表驱动侧支持传递hint参数,但delete操作携带hint的特性是MongoDB服务端4.4版本才正式新增的,低版本服务端根本识别不到delete请求里的hint字段,所以会抛出未知字段错误。 - 第三次传索引名报错的额外可能原因:默认单字段升序索引的名称是
字段名_1,也就是competitionId_1,如果没有自定义索引名,直接传字段名competitionId是找不到对应索引的。
正确解决步骤
- 第一步:先确认MongoDB服务端版本
可以直接通过pymongo查询:
如果返回的版本号低于4.4,无法直接在delete_many中使用hint参数,需要用替代方案,或者升级服务端到4.4及以上版本。print(cluster.server_info()['version']) - 第二步:版本符合要求的前提下,两种正确传参方式:
- 传元组列表格式的索引定义:
our_hint = [('competitionId', 1)] db[table_name].delete_many(filter=our_filter, hint=our_hint)- 传索引的名称字符串(注意是索引的name属性,不是字段名):
如果你建索引的时候没有自定义名称,默认名称为competitionId_1,传参如下:
db[table_name].delete_many(filter=our_filter, hint='competitionId_1')
低版本服务端替代方案
如果MongoDB服务端版本无法升级,可以先通过带hint的find查询拿到待删数据的_id,再执行删除,也能达到索引优化的效果:
# 先通过带hint的查询拿到所有待删_id to_delete = [doc['_id'] for doc in db[table_name].find(our_filter, hint=[('competitionId', 1)], projection={'_id':1})] # 再批量删除 db[table_name].delete_many({'_id': {'$in': to_delete}})
内容的提问来源于stack exchange,提问作者Canovice
相关产品推荐
相关产品推荐

