1

I can't make $nin work with nested arrays, can you guys spot any issue with this query? I'm basically trying to update the status of every document under items to "closed" in case their hash field is not in a list of hashes provided.

db.getCollection('projects').update({
    name: 'test',
    'issues.hash': { $nin: [
                    '8ff28fcc9cbf10c9b690bb331e5609efbd3c526be4f536ebca02cc51bd63eac7',
                    'd5368ad5658ec11103796255d127d26da7f3324cdedbd124bdd5db50812d588e',
                    '37298229097785ebc9d419cc1a3f13e0d090a15ceb9a8e6bea3505366902556d',
                    'fad290f2ddd0e097e4098c3b2c3d65611406cf208a3f86924d45c7736393b44b'
                ]}

    }, 
    {
        $set: { "issues.$.status": "closed" }
    }
)

This is the data:

{
    "_id" : ObjectId("611bb4d2ee06769a5f6d906d"),
    "name" : "test",
    "issues" : [ 
        {
            "_id" : ObjectId("611bb4d20b2fb200167aa588"),
            "status" : "open",
            "hash" : "8ff28fcc9cbf10c9b690bb331e5609efbd3c526be4f536ebca02cc51bd63eac7"
        }, 
        {
            "_id" : ObjectId("611bb4d20b2fb200167aa589"),
            "status" : "open",
            "hash" : "3b83e469049e46b16d3471a188d3f5e3ddbf6b296995a71765bbf17b7289e6ea"
        }, 
        {
            "_id" : ObjectId("611bb4d20b2fb200167aa58a"),
            "status" : "open",
            "hash" : "bef5f50628b669b9930b89cdc040361b9c8cc2b4aab3c2059c171786d38d507e"
        }, 
        {
            "_id" : ObjectId("611bb4d20b2fb200167aa58b"),
            "status" : "open",
            "hash" : "1b4a91eb5de97d6ad7493b6e1ffa48a2a648084b4af7b37916c723533a07c37c"
        }, 
        {
            "_id" : ObjectId("611bb4d20b2fb200167aa58c"),
            "status" : "open",
            "hash" : "bb64ba7b2612856dcd95c3ac2fad3f7368e5d463168545b12f4c869af56b55b7"
        }, 
        {
            "_id" : ObjectId("611bb4d20b2fb200167aa58d"),
            "status" : "open",
            "hash" : "1d5fc04739b10414dea8d327998df4f200f47ce57da243bd578d4ae102f2d670"
        }, 
        {
            "_id" : ObjectId("611bb4d20b2fb200167aa58e"),
            "status" : "open",
            "hash" : "d5368ad5658ec11103796255d127d26da7f3324cdedbd124bdd5db50812d588e"
        }, 
        {
            "_id" : ObjectId("611bb4d20b2fb200167aa58f"),
            "status" : "open",
            "hash" : "37298229097785ebc9d419cc1a3f13e0d090a15ceb9a8e6bea3505366902556d"
        }, 
        {
            "_id" : ObjectId("611bb4d20b2fb200167aa590"),
            "status" : "open",
            "hash" : "fad290f2ddd0e097e4098c3b2c3d65611406cf208a3f86924d45c7736393b44b"
        }
    ]
}

And the is my result:

Updated 0 record(s) in 12ms

Thank you!

1
  • Is this what are you looking for? If it works for you I can add an answer to explain better. Commented Aug 17, 2021 at 14:58

2 Answers 2

2

You have to use arrayFilters in this way:

db.collection.update({
  "name": "test"
},
{
  "$set": {
    "issues.$[element].status": "closed"
  }
},
{
  "arrayFilters": [
    {
      "element.hash": {
        "$nin": [
          "8ff28fcc9cbf10c9b690bb331e5609efbd3c526be4f536ebca02cc51bd63eac7",
          "d5368ad5658ec11103796255d127d26da7f3324cdedbd124bdd5db50812d588e",
          "37298229097785ebc9d419cc1a3f13e0d090a15ceb9a8e6bea3505366902556d",
          "fad290f2ddd0e097e4098c3b2c3d65611406cf208a3f86924d45c7736393b44b"
        ]
      }
    }
  ]
})

Example here.

Note that update query has the format: update(query, update, options) (Check the docs).

So with your find query mongo doesn't find anything. Check this example.

This is why you are telling mongo: "Give me a DOCUMENT where name is test and issues array NOT contains a field called hash with these values".

So, as mongo search by the whole document, there is no any document where hash value is not on the $nin array.

As another example to exaplain better: Check this example where hash value is 1. In this case, find query works because it matches two conditions:

  • There is a field name with value test
  • There is not any field hash into issues with values into $nin array.
Sign up to request clarification or add additional context in comments.

Comments

2

You can use arrayFilters, like this:

db.collection.update({
  "name": "test"
},
{
  "$set": {
    "issues.$[elem].status": "closed"
  }
},
{
  "multi": true,
  "arrayFilters": [
    {
      "elem.hash": {
        "$nin": [
          "8ff28fcc9cbf10c9b690bb331e5609efbd3c526be4f536ebca02cc51bd63eac7",
          "d5368ad5658ec11103796255d127d26da7f3324cdedbd124bdd5db50812d588e",
          "37298229097785ebc9d419cc1a3f13e0d090a15ceb9a8e6bea3505366902556d",
          "fad290f2ddd0e097e4098c3b2c3d65611406cf208a3f86924d45c7736393b44b"
        ]
      }
    }
  ]
})

Here is the working example: https://mongoplayground.net/p/8wZkmlBgKiq

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.