Dmitriy Kisil
Dmitriy Kisil

Reputation: 2998

Pymongo arayfilters not worked

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

Answers (1)

MikkolidisMedius
MikkolidisMedius

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

Related Questions