Reputation: 2998
I have in MongoDB collection named locations
field ip_addresses
. This field looks like this:
[['178.150.147.148'], ['198.16.78.43']]
I want to add a new ip_address at specific position in ip_addresses
. For example, "192.162.78.101" in the first list(where '178.150.147.148' is).
Desired output:
[['178.150.147.148', '192.162.78.101'], ['198.16.78.43']]
My query in pymongo
:
find_index = 0
new_date = "12/29/2019"
ip = "192.162.78.101"
db.locations.find_one_and_update({"date": new_date},
{"$push": {"ip_addresses.$[element]": ip}},
{"multi": False, "arrayFilters": [{"element": {"$eq": find_index}}]},
# Try using each and position but didn't succeed
# "$each": ['ip'],
# "$position": find_index}}},
upsert=True,
return_document=ReturnDocument.AFTER)
But I got error:
pymongo.errors.OperationFailure: No array filter found for identifier 'element' in path 'ip_addresses.$[element]'
Tried searching through pymongo and mongodb docs - if arrayFilters
implement in pymongo, because I couldn't found any example using it. Without arrayFilters
might be the chance to got what I want here?
Upvotes: 0
Views: 223
Reputation: 4844
In pymongo, array filters are specified as an argument to the function, not within an object. This is probably what you are looking for:
find_index = 0
new_date = "12/29/2019"
ip = "192.162.78.101"
db.locations.find_one_and_update({"date": new_date},
{"$push": {"ip_addresses.$[element]": ip}},
upsert=True, multi=False,
array_filters=[{ "element": { "$eq": find_index }}]
return_document=ReturnDocument.AFTER)
However, this works only if find_index
contains an ip address that is in the array you want to append into; i.e, it would work if find_index='178.150.147.148'
. In other words, the above statement is saying: "add '192.162.78.101' to the sub-array that already contains '178.150.147.148'".
If what you want to specify is the index of the sub-array, just use the positional dot notation, like this:
db.locations.find_one_and_update({"date": new_date},
{"$push": {"ip_addresses.0": ip}},
upsert=True, multi=False,
return_document=ReturnDocument.AFTER)
Upvotes: 1