mongomock_motor icon indicating copy to clipboard operation
mongomock_motor copied to clipboard

Odd interaction with `$slice`

Open forana opened this issue 9 months ago • 1 comments

I am encountering an issue when passing nesting a function inside $slice calls, but only with mongomock_motor in use (works fine when regular motor is used). Example code is removing an item from a nested list by index:

Anonymized code:

await db.baskets.update_one(
    {"_id": basket_id},
    [
        {
            "$set": {
                "items": {
                    "$concatArrays": [
                        {"$slice": ["$items", index]},
                        {"$slice": ["$items", index + 1, {"$size": "$items"}]},
                    ]
                }
            }
        }
    ],
)

AsyncIOMotorClient handles this just fine. However, AsyncMongoMockClient encounters an error:

../snip/lib/python3.13/site-packages/mongomock_motor/__init__.py:43: in wrapper
    return getattr(proxy_source, method_name)(*args, **kwargs)
../snip/lib/python3.13/site-packages/mongomock/collection.py:616: in update_one
    self._update(
../snip/lib/python3.13/site-packages/mongomock/collection.py:718: in _update
    self._apply_update_pipeline(existing_document, document, session)
../snip/lib/python3.13/site-packages/mongomock/collection.py:765: in _apply_update_pipeline
    [new_document] = aggregate.process_pipeline(
../snip/lib/python3.13/site-packages/mongomock/aggregate.py:1658: in process_pipeline
    collection = handler(collection, database, options)
../snip/lib/python3.13/site-packages/mongomock/aggregate.py:1558: in _handle_add_fields_stage
    out_value = _parse_expression(value, in_doc, ignore_missing_keys=True)
../snip/lib/python3.13/site-packages/mongomock/aggregate.py:1067: in _parse_expression
    return _Parser(doc_dict, ignore_missing_keys=ignore_missing_keys).parse(expression)
../snip/lib/python3.13/site-packages/mongomock/aggregate.py:255: in parse
    return self._handle_array_operator(k, v)
../snip/lib/python3.13/site-packages/mongomock/aggregate.py:685: in _handle_array_operator
    parsed_list = list(self.parse_many(value))
../snip/lib/python3.13/site-packages/mongomock/aggregate.py:288: in parse_many
    yield self.parse(value)
../snip/lib/python3.13/site-packages/mongomock/aggregate.py:255: in parse
    return self._handle_array_operator(k, v)

pymongo.errors.OperationFailure: Third argument to $slice must be numeric, but is of type: <class 'dict'>

forana avatar Feb 18 '25 19:02 forana

It looks like this issue stems from mongomock's implementation. You might consider reporting it upstream or modifying your implementation to reference inner documents by their IDs rather than using indexes.

michaelkryukov avatar Mar 16 '25 15:03 michaelkryukov