Robin
Robin

Reputation: 41

Update one item of an array which is a property of an object in mongodb and nodejs

Hi I'm trying to update an single item of an array in mongodb with nodejs. My data structure in mongodb is something like this:

{
    "_id": "5e818db59cedd232d83c66cb",
    "project": "projectX",
    "version": 1,
    "salesChannel": "channel42",
    "country": "Austria",
    "book": true,
    "categories": [
      {
        "pieceItems": [
          {
            "category": "pieceItems",
            "identifier": "1.1",
            "registrationHints": "Scan the barcode OR register the itemNumber manually",
            "variant": "Tax-Group 19%",
            "additionalHints": "optionally provided"
          }
        ],
      },
      {
        "weightItems": [
          {
            "category": "weightItems",
            "identifier": "2.1",
            "registrationHints": "Scan the barcode OR register the itemNumber manually",
            "variant": "Tax-Group 19%",
            "additionalHints": "optionally provided"
          },
          {
            "category": "weightItems",
            "identifier": "2.2",
            "registrationHints": "Scan the barcode OR register the itemNumber manually",
            "variant": "Tax-Group 19%",
            "additionalHints": "optionally provided"
          }
        ],
      }
    ]
}

This is the code with I tryed but nothing changes in my database:

exports.editCategoryInBook = function (body, project, salesChannelName, country) {
  mongoClient.connect(mongoUrl, async (err, client) => {
    assert.equal(null, err)
    const db = client.db(dbName)
    var categoryName = Object.keys(body)[0]
    var updateCategory = `categories.$.${categoryName}`
    var categoryValue = body[categoryName]
    console.log(`$set: { ${updateCategory}: categoryValue }`)
    db.collection(project).updateOne({
      "book": true,
      "salesChannel": salesChannelName,
      "country": country
    }, {
      $set: { [updateCategory]: categoryValue },
      $currentDate: { lastModified: true }
    })
    client.close()
  })
  return new Promise(function (resolve, reject) {
    resolve();
  });
}

This is the body variable which is passed to the function:

{
    "pieceItems": [
    {
        "category": "Piece Item",
        "identifier": 1.11,
        "registrationHints": "Scan the barcode OR register the itemNumber manually; some more hints could follow",
        "variant": "Tax-Group 19%",
        "additionalHints": "some string hint to give bonus information about this item",
        "name": "Buntsteinputz 8508",
        "EAN": 4003498690070,
        "PLU": 3822584,
        "price": "51,95€"
    },
    {
        "category": "Piece Item",
        "identifier": 1.2,
        "registrationHints": "Scan the barcode OR register the itemNumber manually; some more hints could follow",
        "variant": "Tax-Group 7%",
        "additionalHints": "some string hint to give bonus information about this item",
        "name": "Buntsteinputz 8508",
        "EAN": 4003498690070,
        "PLU": 3822584,
        "price": "51,95€"
    }
  ]
}

I get the following output from the console.log:

$set: { categories.$.pieceItems: categoryValue }

And I get the following Error:

MongoError: The positional operator did not find the match needed from the query.
at Function.create (C:\Users\rkrause\node_modules\mongodb\lib\core\error.js:43:12)
at toError (C:\Users\rkrause\node_modules\mongodb\lib\utils.js:149:22)
at C:\Users\rkrause\node_modules\mongodb\lib\operations\common_functions.js:376:39
at C:\Users\rkrause\node_modules\mongodb\lib\core\connection\pool.js:404:18
at processTicksAndRejections (internal/process/task_queues.js:82:9)

Upvotes: 0

Views: 181

Answers (1)

So now the problem is, that it doesn't want to update all the things in it unless it matches some search query in the filter part. But i think we can trick it into doing that like:

const WhatToSet = `categories.$.${categoryName}`


db.collection(project).updateOne({
  "book": true,
  "salesChannel": salesChannelName,
  "country": country,
  [`categories.${categoryName}`]: {$exists: true}
}, {
  $set: { [WhatToSet]: categoryValue },
  $currentDate: { lastModified: true }
})

I hope this helps

Upvotes: 1

Related Questions