Pymongo查询MongoDB Atlas返回空列表 find_one返回None报错问题
问题原因
1. 当前直接报错的原因
你执行visitors = list(db.find().sort('_id', -1))后,visitors是一个存储文档的列表,不能直接用字符串_id作为索引取值,必须先取出列表中对应位置的文档对象,再取字段值。
2. 查询返回空列表/find_one返回None的常见原因
- 插入用户的操作未完成就执行了查询逻辑:如果插入是异步操作,未等待写入完成就触发读操作,会读不到数据
- MongoDB Atlas集群同步延迟:多节点部署下写入操作还未同步到读节点,导致读请求返回空
- 集合对象/权限配置错误:读操作指向的集合和写入集合不一致,或是数据库账号没有对应集合的读权限
修复方案
第一步:修复列表索引报错,增加空值校验
修改make_photo函数的逻辑如下:
def make_photo(frame): save.make_directory('pics') # 加limit(1)提升查询性能,只查最新的1条即可 visitors = list(db.find().sort('_id', -1).limit(1)) print(visitors) # 先校验查询结果是否为空 if not visitors: print("未查询到最新用户数据,请确认写入逻辑") return "fail" # 先取列表第一个元素(最新插入的文档),再取_id字段 latest_user = visitors[0] small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) face_locations = face_recognition.face_locations(small_frame) if len(face_locations) == 0: print("face detection fails") return "fail" else: path = 'pics/img0.jpg' save.save_photo(path, frame) result = encoding_picture(path, latest_user['_id']) if result == "success": print("Success to register") else: print("Check picture path") return result
如果改用find_one查询,写法如下,也需要先做非空判断避免NoneType报错:
latest_user = db.find_one(sort=[('_id', -1)]) if not latest_user: print("未查询到用户数据") return "fail" user_id = latest_user['_id']
第二步:排查查询返回空的问题
- 确保插入用户的操作完全执行完成后,再调用
make_photo执行读操作,如果插入逻辑是异步实现,必须等待异步任务完成再触发后续逻辑 - 写入操作可配置写确认级别为
w: "majority",确保数据写入大多数节点后再返回,读操作指定读偏好为primary直接从主节点读取,避免集群同步延迟 - 确认读操作指向的集合和写入用户的集合是同一个,检查Atlas账号的权限配置,确保有对应集合的读权限
额外优化建议
encoding_picture函数中face_recognition.face_encodings(small_image)[0]需要加非空判断,若未提取到人脸特征直接取索引0也会触发报错,建议先校验返回列表长度再取值。
内容的提问来源于stack exchange,提问作者Hakim Kadhi
相关产品推荐
相关产品推荐

