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

admin2025-04-20  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.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745125463a286398.html

最新回复(0)