最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - Update an array value in document with Pymongo - Stack Overflow

programmeradmin0浏览0评论

I am creating a tracker that tracks the usage of invites on discord and who used which invite when a member joins. I am storing the data in mongodb. I am having trouble update the uses value which I have stored in an array. I want the value to increment by one after a use so it can be reflected in the database.

The document below

{
  "_id": {
    "$numberLong": "1290376241140076606"
  },
  "log_channels": {
    "channel_log": {
      "$numberLong": "1343383983291105360"
    },
    "voice_log": {
      "$numberLong": "1345281298788253726"
    },
    "welcome_log": {
      "$numberLong": "1344993348808605727"
    },
    "guild_log": {
      "$numberLong": "1343355706547634290"
    },
    "invite_log": {
      "$numberLong": "1343356487602274325"
    },
    "join_log": {
      "$numberLong": "1343355776890310708"
    },
    "leave_log": {
      "$numberLong": "1343355776890310708"
    },
    "ban_log": {
      "$numberLong": "1343356340201852959"
    },
    "unban_log": {
      "$numberLong": "1343356340201852959"
    },
    "message_log": {
      "$numberLong": "1343383983291105360"
    }
  },
  "voice_activity": {},
  "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"
      ]
    },
    {
      "stTaCBQV": [
        0,
        "1118711272054198322",
        "2025-03-02 05:00:09.580000+00:00"
      ]
    }
  ]
}

The code below

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:
    for tracked_invite in tracked_invites:
        tracked_code = next(iter(tracked_invite))
        tracked_uses = tracked_invite.get(tracked_code)[0]
        if tracked_code == invite.code and tracked_uses != invite.uses:
            await db.guilds.update_one(filter,{'$inc': {f'invites.$.{tracked_code}.{tracked_uses}': 1 } })
            return tracked_invite.get(tracked_code)[1]

The invite pool are the current invites stored by discord in a server and the tracked invites are the invites in the collection. It is supposed to compare the invites codes. When it finds a match in invite codes, it checks to see if the uses match each other. If the uses don't match, that identifies as the invite that was used for a member to join. I want to increment the usage value by one to reflect the proper usuage value in the database. When I run the code

await db.guilds.update_one(filter,{'$inc': {f'invites.$.{tracked_code}.{tracked_uses}': 1 } })

This is the line of code in particular that is giving me trouble. It is not increment the value in the array. So the value of 0 which is the first element in the array is what I am attempting to increment by one.

I am creating a tracker that tracks the usage of invites on discord and who used which invite when a member joins. I am storing the data in mongodb. I am having trouble update the uses value which I have stored in an array. I want the value to increment by one after a use so it can be reflected in the database.

The document below

{
  "_id": {
    "$numberLong": "1290376241140076606"
  },
  "log_channels": {
    "channel_log": {
      "$numberLong": "1343383983291105360"
    },
    "voice_log": {
      "$numberLong": "1345281298788253726"
    },
    "welcome_log": {
      "$numberLong": "1344993348808605727"
    },
    "guild_log": {
      "$numberLong": "1343355706547634290"
    },
    "invite_log": {
      "$numberLong": "1343356487602274325"
    },
    "join_log": {
      "$numberLong": "1343355776890310708"
    },
    "leave_log": {
      "$numberLong": "1343355776890310708"
    },
    "ban_log": {
      "$numberLong": "1343356340201852959"
    },
    "unban_log": {
      "$numberLong": "1343356340201852959"
    },
    "message_log": {
      "$numberLong": "1343383983291105360"
    }
  },
  "voice_activity": {},
  "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"
      ]
    },
    {
      "stTaCBQV": [
        0,
        "1118711272054198322",
        "2025-03-02 05:00:09.580000+00:00"
      ]
    }
  ]
}

The code below

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:
    for tracked_invite in tracked_invites:
        tracked_code = next(iter(tracked_invite))
        tracked_uses = tracked_invite.get(tracked_code)[0]
        if tracked_code == invite.code and tracked_uses != invite.uses:
            await db.guilds.update_one(filter,{'$inc': {f'invites.$.{tracked_code}.{tracked_uses}': 1 } })
            return tracked_invite.get(tracked_code)[1]

The invite pool are the current invites stored by discord in a server and the tracked invites are the invites in the collection. It is supposed to compare the invites codes. When it finds a match in invite codes, it checks to see if the uses match each other. If the uses don't match, that identifies as the invite that was used for a member to join. I want to increment the usage value by one to reflect the proper usuage value in the database. When I run the code

await db.guilds.update_one(filter,{'$inc': {f'invites.$.{tracked_code}.{tracked_uses}': 1 } })

This is the line of code in particular that is giving me trouble. It is not increment the value in the array. So the value of 0 which is the first element in the array is what I am attempting to increment by one.

Share Improve this question edited Mar 3 at 14:21 aneroid 16.4k3 gold badges40 silver badges75 bronze badges asked Mar 2 at 10:02 user29836029user29836029 92 bronze badges 1
  • The problem lies in the way you're constructing the update query. Specifically, the $inc operator is being applied to an incorrect field path. Should increment as follows await db.guilds.update_one( filter, {'$inc': {f'invites.$.{tracked_code}.0': 1}} ) – steve-ed Commented Mar 2 at 10:28
Add a comment  | 

1 Answer 1

Reset to default 1

Since invites is an array, you need to provide an array filter to indicate which object in it should get updated. Otherwise, all the invites would get updated. Also, the selector for the increment should have the first element index (0).

The update query would be:

db.guilds.update({
  // your `guild.id` here
  "_id": { "$numberLong": "1290376241140076606" }
},
{
  "$inc": {
    // your invite code here
    "invites.$[inv].UrxbKHJV.0": 1
  }
},
{
  arrayFilters: [
    {
      // your invite code here
      "inv.UrxbKHJV": { $ne: null }
    }
  ]
})

Mongo Playground 1

Note that you don't need to get the tracked_uses first, the increment operator handles that. In Python, use the array_filter argument for update_one/many():

await db.guilds.update_one(
    filter,
    {'$inc': {f'invites.$[inv].{tracked_code}.0': 1}},
    array_filters=[{f'inv.{tracked_code}': {'$ne': None}}]
)

This only requires the guild id and tracked code. So the two nested-for-loops shouldn't be necessary.

Since the invite code doesn't include the guild id and invites are unique, you don't actually need to get the guild id first - you can make that part of the filter:

db.guilds.update({
  // your invite code here
  "invites": {
    $elemMatch: {
      "UrxbKHJV": { $ne: null }
    }
  }
},
{
  "$inc": {
    // your invite code here
    "invites.$[inv].UrxbKHJV.0": 1
  }
},
{
  arrayFilters: [
    {
      // your invite code here
      "inv.UrxbKHJV": { $ne: null }
    }
  ]
})

Mongo Playground 2

So for your code:

filter = {"invites": {"$elemMatch": {tracked_code: {"$ne": None}}}}

Btw, it would be better if your invites array was stored as name: value pairs, the Attribute Pattern. Then it's easier to use in array filters and to create indexes. Then the invites would look like:

"invites": [
  {
    "code": "UrxbKHJV",
    "uses": 0,
    "some_other_code": "1118711272054198322",
    "created_at": "2025-03-01 15:18:55.838000+00:00"
  },
  {
    "code": "bVnjb7ser9",
    "uses": 0,
    "some_other_code": "1118711272054198322",
    "created_at": "2025-03-01 16:27:03.759000+00:00"
  },
  {
    "code": "stTaCBQV",
    "uses": 0,
    "some_other_code": "1118711272054198322",
    "created_at": "2025-03-02 05:00:09.580000+00:00"
  }
]

That has a much simpler update query: Mongo Playground 3.

发布评论

评论列表(0)

  1. 暂无评论