'How to search in array of array of object in mongodb

Suppose the mongodb document(table) 'users' is

{
    "_id": "6065923bc5d509071857f6e6",
    "version": [
        {
            "name": "1.1.0",
            "status": "not Approved",
            "_id": "606592b1c5d509071857f6e7",
            "files": [
                {
                    "_id": "606592b3c5d509071857f6e8",
                    "url": "https://google.com/1.png",
                    "status": "awaiting"
                },
                {
                    "_id": "606592b8c5d509071857f6e9",
                    "url": "https://google.com/2.png",
                    "status": "awaiting"
                }
            ]
        }
    ]
}

I want to update the status of this "***https://google.com/1.png***" image Can we do using findOneAndUpdate? because i want to return the updated Object



Solution 1:[1]

Let's say you want to search for the awaiting status for the collection users

db.users.find({"version.files.status":"awaiting"}).pretty()

It will automatically search within the arrays.

Updating, however, is a bit different and you should use arrayFilter:

db.users.updateOne(
  {
    "version.files._id": "606592b3c5d509071857f6e8",
  },
  {
    $set: {
      "version.$[version].files.$[file].url": "something else",
    },
  },
  {
    arrayFilters: [
      { "version._id": "606592b1c5d509071857f6e7" },
      { "file._id": "606592b3c5d509071857f6e8" },
    ],
  }
);

Make sure to have an index on your find query:

For the above example

db.users.createIndex({"version.files._id":1},{background:true})

Many more example available on the Mongo Doc


EDIT

As per your comment, here is a working example:

db.users.findOneAndUpdate(
  { "version.files._id": "606592b3c5d509071857f6e8" },
  {
    $set: {
      "version.$[version].files.$[file].url": "Test URL",
      "version.$[version].files.$[file].status": "Test status",
    },
  },
  {
    returnNewDocument: true,
    arrayFilters: [
      { "version._id": "606592b1c5d509071857f6e7" },
      { "file._id": "606592b3c5d509071857f6e8" },
    ],
  }
);

enter image description here

Solution 2:[2]

You can do it like this:

    await db.collection('users').updateOne(
        { _id: users._id },
        { $set: { "version.$[version].files.$[file].url": "newStatus" } },
        {
            arrayFilters: [
                { "version._id": "606592b1c5d509071857f6e7" },
                { "url": "https://google.com/1.png" }
            ]
        }
    );

Edit:

If there's more than one record with "https://google.com/1.png" It'll update the status of the first record it encountered.

Edit2: Thanks callmemath for fix my mistake

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 callmemath