mongodbmongodb-querypymongoflask-pymongo

MongoDB field must be an array


Currently I have a collection with the following documents:

[
    {
        "_id": ObjectId("628e6bd640643f97d6517c75"),
        "company": "bau",
        "current_version": 0,
        "form_name": "don't know",
        "history": [],
        "id": "23421123-24a9-4a45-a12f-27a330152ax3",
        "is_active": True,
        "user_id": "999",
    },
    {
        "_id": ObjectId("628eaffe4b8ae2ccdeb9305c"),
        "company": "vrau",
        "current_version": 0,
        "form_name": "exemplo",
        "history": [
            {
                "content": [
                    {
                        "field_id": 0,
                        "label": "insira um texto",
                        "placeholder": "qualquer texto",
                        "type": "text",
                    }
                ],
                "layout": [
                    {"field_id": 0, "h": 10, "type": "text", "w": 100, "x": 0, "y": 0}
                ],
                "responses": [
                    {
                        "client_id": 100,
                        "response_date": "2020-01-02",
                        "values": [{"field_id": 0, "value": "um texto"}],
                    },
                    {
                        "client_id": 2,
                        "response_date": "2020-01-01",
                        "values": [{"field_id": 0, "value": "roi"}],
                    },
                ],
                "version": 0,
            }
        ],
        "id": "33b66684-24a9-4a45-a12f-27a330152ac8",
        "is_active": True,
        "user_id": "1",
    },
]

I want to change the response fromthe client_id = '2' by I'm receiving the following error:

pymongo.errors.WriteError: The field 'history.0.responses.1' must be an array but is of type object in document {_id: ObjectId('628eaffe4b8ae2ccdeb9305c')}, full error: {'index': 0, 'code': 2, 'errmsg': "The field 'history.0.responses.1' must be an array but is of type object in document {_id: ObjectId('628eaffe4b8ae2ccdeb9305c')}"}

I don't know what I'm doing wrong and this error doesnt make sense to me cuz reponses is an array.

my current query:

collection.update_many(
    {"id": "33b66684-24a9-4a45-a12f-27a330152ac8", "history.version": 0},
    {
        "$push": {
            "history.$[h].responses.$[r]": {
                "client_id": 2,
                "response_date": "2020-01-01",
                "values": [{"field_id": 0, "value": "roi"}],
            }
        }
    },
    array_filters=[{"h.version": 0}, {"r.client_id": "2"}],
)

Is there another to do it?


Solution

  • It is because you are also performing filter on r, which already resolves to object level in responses array.

    You can simply abandon the r arrayFilter if you simply want to push to responses array.

    collection.update_many(
        {"id": "33b66684-24a9-4a45-a12f-27a330152ac8", "history.version": 0},
        {
            "$push": {
                "history.$[h].responses": {
                    "client_id": 2,
                    "response_date": "2020-01-01",
                    "values": [{"field_id": 0, "value": "roi"}],
                }
            }
        },
        array_filters=[{"h.version": 0}],
    )
    

    Here is the Mongo playground for your reference. (in native js syntax)


    You should use $set instead of $push if you want to update the entry instead of adding an entry. In your given example, the client_id is int while your arrayFilter is string. It could cause problem if it is not intended.

    collection.update_many(
        {"id": "33b66684-24a9-4a45-a12f-27a330152ac8", "history.version": 0},
        {
            "$set": {
                "history.$[h].responses.$[r]": {
                    "client_id": 2,
                    "response_date": "2020-01-01",
                    "values": [{"field_id": 0, "value": "roi"}],
                }
            }
        },
        array_filters=[{"h.version": 0}, {"r.client_id": 2}],
    )
    

    Here is the Mongo playground for your reference. (in native js syntax)