1

I am trying to create many update operations for bulk updates.

I am trying to select an element (dictionary) in an array by array filter, but update (or more precisely upsert) another field (in the bellow example new_field) on the element than the field the array filter is applied to.

So in short:

  • Have Array of dictionaries
  • Select element in the array by key_1
  • Upsert key_2:value_2 on previously selected element

I am currently trying to get this working with one (test)record.

the (test)record looks like this:

{
  '_id': '001d1a70fdc77812053d',
  'images': {
    'photos': [{'id':'jxptm90a'}]
  },
  ...
}

the update operation looks like this:

update_operation = pymongo.UpdateOne(
    filter={'_id': '001d1a70fdc77812053d'},
    update={
        '$currentDate': {'oplog_skip': True},
        '$set': { "images.photos.$[new_field]": 2 },

    },
    upsert=False,
    array_filters=[ { 'id': 'jxptm90a' }]
)

however, executing the command like this:

  db.collection.bulk_write([update_operation])

results in the following error:

{'writeErrors': [{'index': 0, 'code': 2, 'errmsg': "No array filter found for identifier 'test' in path 'images.photos.$[test]'", 'op': SON([('q', {'_id': '001d1a70fdc77812053d'}), ('u', {'$currentDate': {'oplog_skip': True}, '$set': {'images.photos.$[test]': 2}}), ('multi', False), ('upsert', False), ('arrayFilters', [{'id': 'jxptm90a'}])])}], 'writeConcernErrors': [], 'nInserted': 0, 'nUpserted': 0, 'nMatched': 0, 'nModified': 0, 'nRemoved': 0, 'upserted': []}
---------------------------------------------------------------------------
BulkWriteError                            Traceback (most recent call last)
<ipython-input-74-d31fe774222f> in <module>
      5 
      6     try:
----> 7         db.collection.bulk_write([update])
      8     except _pymongo.errors.BulkWriteError as bwe:
      9         print(bwe.details)

~/anaconda3/envs/py363/lib/python3.6/site-packages/pymongo/collection.py in bulk_write(self, requests, ordered, bypass_document_validation, session)
    495 
    496         write_concern = self._write_concern_for(session)
--> 497         bulk_api_result = blk.execute(write_concern, session)
    498         if bulk_api_result is not None:
    499             return BulkWriteResult(bulk_api_result, True)

~/anaconda3/envs/py363/lib/python3.6/site-packages/pymongo/bulk.py in execute(self, write_concern, session)
    511                 self.execute_no_results(sock_info, generator)
    512         else:
--> 513             return self.execute_command(generator, write_concern, session)
    514 
    515 

~/anaconda3/envs/py363/lib/python3.6/site-packages/pymongo/bulk.py in execute_command(self, generator, write_concern, session)
    339 
    340         if full_result["writeErrors"] or full_result["writeConcernErrors"]:
--> 341             _raise_bulk_write_error(full_result)
    342         return full_result
    343 

~/anaconda3/envs/py363/lib/python3.6/site-packages/pymongo/bulk.py in _raise_bulk_write_error(full_result)
    138         full_result["writeErrors"].sort(
    139             key=lambda error: error["index"])
--> 140     raise BulkWriteError(full_result)
    141 
    142 

BulkWriteError: batch op errors occurred

1 Answer 1

1

The filter identifier must match the $set operation; e.g. something like:

update_operation = pymongo.UpdateOne(
    filter={'_id': '001d1a70fdc77812053d'},
    update={
        '$currentDate': {'oplog_skip': True},
        '$set': { "images.photos.$[id]": 2 },
    },
    upsert=False,
    array_filters=[ { 'id': 'jxptm90a' }]
)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.