Reputation: 19
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.
Upvotes: 1
Views: 36
Reputation: 15987
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 }
}
]
})
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 }
}
]
})
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.
Upvotes: 0