使用PyMongo更新MongoDB文档中Discord邀请使用次数
解决MongoDB中Discord邀请使用次数自增的问题
问题根源
你的代码存在两个关键错误:
- 数组元素定位失败:
update_one的filter仅匹配了_id,MongoDB的$操作符无法确定要更新invites数组中的哪一个元素,必须在filter中添加对目标邀请码的匹配条件。 - 更新路径错误:你用当前的使用次数值(比如
0)作为数组索引拼接路径,而实际上使用次数是目标数组的第一个元素(索引固定为0),正确路径应该指向该固定位置。
修正后的代码
filter = {'_id': guild.id} invite_pool = await guild.invites() query = await db.guilds.find_one(filter) tracked_invites = query['invites'] for invite in invite_pool: # 构建邀请码到跟踪数据的映射,避免嵌套循环(可选优化) tracked_map = {next(iter(item)): item[next(iter(item))] for item in tracked_invites} if invite.code in tracked_map: tracked_uses = tracked_map[invite.code][0] if tracked_uses != invite.uses: # 构建包含数组元素匹配的filter,定位到目标邀请码所在的数组项 update_filter = { '_id': guild.id, 'invites': {'$elemMatch': {invite.code: {'$exists': True}}} } # 正确的更新路径:指向invites数组中匹配项的邀请码对应的数组第一个元素 await db.guilds.update_one( update_filter, {'$inc': {f'invites.$.{invite.code}.0': 1}} ) return tracked_map[invite.code][1]
关键修正点说明
- 精准定位数组元素:使用
$elemMatch在filter中匹配invites数组中包含目标邀请码的元素,确保$操作符能正确指向要更新的数组项。 - 固定索引路径:直接使用
0作为数组索引,因为使用次数始终是邀请码对应数组的第一个元素,无需用当前数值拼接路径。 - 循环优化:将tracked_invites转换为字典映射,把嵌套循环改为单次查找,提升代码效率。
可选结构优化建议
当前invites数组的结构(每个元素是单键对象)不利于高效查询和更新,建议将其改为对象结构:
"invites": { "UrxbKHJV": [0,"1118711272054198322","2025-03-01 15:18:55.838000+00:00"], "bVnjb7ser9": [0,"1118711272054198322","2025-03-01 16:27:03.759000+00:00"] }
这样更新操作会更简洁,无需处理数组定位:
await db.guilds.update_one( {'_id': guild.id}, {'$inc': {f'invites.{invite.code}.0': 1}} )
内容的提问来源于stack exchange,提问作者user29836029
相关产品推荐
相关产品推荐

