0

Here is my collection object structure

"_id" : ObjectId("xxxxxxxxxxxxxxxxxxxxxxxx"),
"Name": "HelloWorld",
"OtherFields": "OtherValues",
"Projects" : [ 
    {
        "Project" : {
            "key" : 111
        },
        "Category" : [ 
            {
                "No" : "123"
            }, 
            {
                "No" : "987"
            }
        ]
    },
    {
        "Project" : {
            "key" : 222
        },
        "Category" : [ 
            {
                "No" : "123"
            }, 
            {
                "No" : "987"
            }
        ]
    }
]

I want to delete element with Category No「123」in Project with key 111

Closer thing that I did was

db.project_collection.updateOne({"_id": ObjectId("collection_obj_id")}, {"$pull": { "Projects": {"$and": [ {"Project.key": 111)}, {"Category.No": "123"} ] }} })

Live example

This command removing whole element inside "Projects" object

But I want to delete only "Projects""Category"[0] subelement which has No 123.

When I trying to change "Projects" after "$pull" to something like "Projects.Category" or "Projects.$.Category"

The positional operator did not find the match needed from the query

error occures.

So is it possible to delete subelement without creating own backend logic?

rzlvmp
  • 7,512
  • 5
  • 16
  • 45
  • You need to use the Array Update Operator [positional $](https://docs.mongodb.com/v4.2/reference/operator/update/positional/index.html). – prasad_ Nov 06 '20 at 08:24
  • I already tried Projects.$, Projects.$.Category.$, Projects.Category.$, Projects.$.Category with no luck – rzlvmp Nov 06 '20 at 08:32
  • Yes, you can try the answer below by J.F. Another example [here](https://docs.mongodb.com/v4.2/reference/operator/update/pull/#remove-items-from-an-array-of-documents) using `$pull`. – prasad_ Nov 06 '20 at 08:37
  • One of the answers in the marked duplicates dictates a solution in the form `db.collection.update({ _id: "xxxxxxxxxxxxxxxxxxxxxxxx" }, { $pull: { "Projects.$[elem].Category": { "No": "123" } } }, { arrayFilters: [ { "elem.Project.key": 111 } ] })` – chridam Nov 06 '20 at 09:37

1 Answers1

1

Knowing project.key and category.no you can use this query:

db.collection.update({
  "_id": 1,
  "Projects.Project.key": 111
},
{
  "$pull": {
    "Projects.$.Category": {
      "No": "123"
    }
  }
})

With the updated JSON, the $ operator is nedded.

This query basically point to a document with key: 111 and _id: 1 and using $ do the pull. So it will pull the 'pointed' element which match no: "123".

Updated example here

I have added another document with _id: 2 to check that only one with _id:1 is updated.

J.F.
  • 13,927
  • 9
  • 27
  • 65
  • no luck :( `WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })` I can use `{"project.key": 111}` for finding element, but even if I find it I can't change – rzlvmp Nov 06 '20 at 08:51
  • Sorry, JSON data in my question was little bit not complete. Added keys for better understanding. Data in your example little bit differs – rzlvmp Nov 06 '20 at 08:55
  • Updated answer with the new JSON format. Hope it helps. – J.F. Nov 06 '20 at 09:05
  • Brilliant! Thank you! Actually I need to update specific object_id, so can you edit your answer query like this https://mongoplayground.net/p/KoMHSFcQyUf And I will check you answer as correct – rzlvmp Nov 06 '20 at 09:15
  • Answer updated :) – J.F. Nov 06 '20 at 09:19