help me with this problem:
I using pymongo to update my mongoDB database using this code:
updates = {"$inc":{}}
user_ip = "127.0.0.1"
updates["$inc"][f"ips.{user_ip}"] = 1
creates something like this in the mongoDB document:
"ips": {
"127": {
"0": {
"0": {
"1": 1
}
}
}
}
but I want it to be like:
"ips": {
"127.0.0.1": 1
}
I cannot replace the . of the ip-address to any other characters in the DB because of some compatibility issues.
but if I do this it works fine:
url_data["ips"][user_ip] = url_data["ips"].get(user_ip, 0) + 1
updates["$set"]["ips"] = url_data["ips"]
url_data is the full document and querying it and updating it whole is not efficient for me
Hi @harry_potter3 ,
After reviewing your question, I would say updating this nested field is anti-pattern. Typically, top-level fields with dot notation can be handled ; however, for this case, it both a nested field and using dot notation, so it may not be possible.
Here’s more information on the limitations of using dot or dollar notation in the field name .
Do you mind sharing the compatibility issue?
aneroid
(Anirudh Dutt)
March 25, 2025, 11:25am
3
Assuming you’re on MongoDB 5 or above, to avoid issues with the dots in the IP address being treated as a path expression, you will need to use $getField and $setField .
Put that in an update aggregation pipeline to first get the current value, add 1, then set that as the value. In Python, you could do:
user_ip = "127.0.0.1"
update_pipeline = [
{
"$set": {
"ips": {
"$setField": {
"field": user_ip,
"input": "$ips",
"value": {
"$add": [
{
"$getField": {
"field": user_ip,
"input": "$ips",
}
},
1
]
}
}
}
}
}
]
collection.update_many({ <user filter here> }, update_pipeline)
Mongo Playground example with more docs . Note that non-matching IP addresses are un-changed.
aneroid
(Anirudh Dutt)
March 25, 2025, 11:40am
4
The real anti-pattern here is the usage of the IP address as the key. Instead having the IP addresses as the keys like this:
ips: {
"127.0.0.1": 100,
"192.168.0.1": 50
}
You should be using known keys/names as the field and value. That is the Attribute Pattern :
ips: [
{addr: "127.0.0.1", count: 100},
{addr: "192.168.0.1", count: 50},
]
Then you could use a standard operation to Update Documents in an Array :
db.collection.update({
_id: 1, // userID
"ips.addr": "127.0.0.1" // IP address
},
{
$inc: {
"ips.$.count": 1
}
})
Mongo Playground update query with Attribute Pattern
1 Like