Performing a single database call to insert multiple subdocuments at once

If I have a document containing an array of objects.

Data = {
  _id: 1,
  total_amount: 0,
  subDataArray: [
  {      
   _id: 1,
   amount: 0   
  },
  {      
   _id: 2,
   amount: 1   
  },
  ...
 ]
}

Updating the total_amount can be done simply like this...

Data.updateOne({ _id }, { $inc: { total_amount: 1} })

However, incrementing the amounts in subDataArray is more complex. If I have an array of updates for Data.subDataArray

var newSubDataArray = [
  {      
   _id: 1,
   amount: 5   
  },
  {      
   _id: 2,
   amount: 5   
  },
]

Is there a way to increment all amounts in Data.subDataArray with just one operation? Keep in mind that newSubDataArray may not always contain every item present in subDataArray, so it would require upsert behavior.

Can this even be achieved?

EDIT: Just to clarify, each amount value in newSubDataArray could differ from one another. The goal is to increment each existing subDataArray item's amount by the respective value found in newSubDataArray based on matching IDs.

Answer №1

Since my previous response did not fully address the question, here is a revised explanation.

In MongoDB, it is not possible to update multiple array elements in one call; you need to make individual calls for each new array element. You can utilize arrayFilters to update all items that match the current element. Below is an example showcasing different behaviors:

Original document:

{ 
    "_id" : 1.0, 
    "doc_amount" : 0.0, 
    "subDocsArray" : [
        {
            "_id" : 1.0, 
            "amount" : 20.0
        }, 
        {
            "_id" : 2.0, 
            "amount" : 31.0
        }, 
        {
            "_id" : 3.0, 
            "amount" : 3.0
        }, 
        {
            "_id" : 5.0
        }
    ]
}

Applying the below script:

var newSubDocsArray = [
  {      
   _id: 1,
   amount: 3  
  },
  {      
   _id: 2,
   amount: 8   
  },
    {      
   _id: 4,
   amount: 7   
  },
      {      
   _id: 5,
   amount: 9   
  },
];


newSubDocsArray.forEach(function(newSubDoc){
  db.getCollection("test").update(
    {_id:1},   
    {$inc:{"subDocsArray.$[subdoc].amount":newSubDoc.amount}},   // Note the use of $[subdoc]
    { multi: true,
       arrayFilters: [ { "subdoc._id": newSubDoc._id } ]
    }
  )
})

This script will result in:

{ 
    "_id" : 1.0, 
    "doc_amount" : 0.0, 
    "subDocsArray" : [
        {
            "_id" : 1.0, 
            "amount" : 23.0   // +3
        }, 
        {
            "_id" : 2.0, 
            "amount" : 39.0   // +8
        }, 
        {
            "_id" : 3.0, 
            "amount" : 3.0    // unchanged
        }, 
        {
            "_id" : 5.0, 
            "amount" : 9.0    // created and set to 9
        }
    ]
}

Key points to note:

  • The item with _id 3 remains unchanged as it is not present in the newSubDocsArray.
  • The item with _id 4 is not created in the array as the arrayFilters do not find a matching element.
  • The items with _id 5 have a new amount field created.

Answer №2

One way to accomplish this is by using the $[] array update operator:

db.getCollection("test").update(
  {_id:1},   
  {$inc:{"subDocsArray.$[].amount":1}}
)

Answer №3

To modify a specific sub-array element in MongoDB, you can use the following syntax:

Start by specifying the criteria: { _id: 1,'subDocsArray._id' : 1}

Then update the item using: {$inc :{'subDocsArray.$.amount':1}}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Text in Angular vanishes upon reopening

I have a code snippet where I am trying to allow the user to edit and save a paragraph displayed on a side panel of the main page. Although the code works fine, allowing users to update the text and see it reflected in the network upon saving, there seems ...

Struggling to insert HTML into an element using JavaScript or jQuery within a function

I'm currently experimenting with implementing smooth page transitions using Barba. The following is my code snippet for adding some HTML when a new page is loaded. Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, conta ...

Injecting dynamic content using JavaScript

My goal is to develop a web page where clicking on any of the three images will cause the content to be inserted into the empty div located above the image links. Below is the JavaScript code I'm using: <script type="text/javascript" src="js/jque ...

The Ionic2 http post request is missing the 'Access-Control-Allow-Origin' header

Here is the complete code snippet: this.http.post(link, data, { headers: headers }) .map(res => res.json()) .subscribe(data => { this.data.response = data._body; }, error => { console.log("Oops! An error occurred"); ...

Upon running `npm start`, an unexpected token error arises in the file originating from a local

After developing my first-app with the help of create-react-app, I incorporated some components from Material-UI. Everything was running smoothly when I launched it using npm start. Upon completion, I decided to extract the nice-component into its own fol ...

Issues with Mega Menu functionality preventing items from being clickable and links from properly navigating

Recently, I encountered a strange issue related to the integration of a mega menu found at . Unfortunately, despite integrating the mega menu, the Category and sub category links seem unresponsive - they are not directing me to the desired links. I suspec ...

What is the best way to incorporate ajax into a Wordpress theme?

I'm currently attempting to incorporate ajax functionality into my WordPress website There are two essential files for this task: a PHP file and a JS file Here is an example of the PHP code located in combo_check-out.php function iRange($first, $la ...

Load HTML content without having to refresh the page

I'm struggling to decide whether I should have the html hidden before it is loaded or pulled from another source. My goal is to display a form on one page and dynamic content on other pages. The form data needs to be saved in mongo db, and when the p ...

How can I show or hide all child elements of a DOM node using JavaScript?

Assume I have a situation where the HTML below is present and I aim to dynamically conceal all the descendants of the 'overlay' div <div id="overlay" class="foo"> <h2 class="title">title</h2> ...

Obtaining data from an ajax request in node.js

My webpage has a feature that triggers an ajax request: $.ajax({ type: 'POST', url: '/usernamecheck', data: {"username":username}, success: function(taken){ ...

Learn how to incorporate a conditional $match condition in MongoDB

Below is the schema that I am currently working with: { f1: "test", f2: "something", type: "A", date: "2018-11-01T00:00:00.000Z", deleted: false }, { "f1": "check", type: "B", deleted: false } I am now looking to retrieve all data ...

Adding new fields to existing documents in MongoDB

In my schema, I have an array called "like" which stores the users who have liked my post. Recently, I added a field called "likeCount" with a default value of 0. How can I add a new field in MongoDB to automatically update the likeCount based on the lengt ...

Leveraging Angular 4 component as a custom widget within a static website

Is it possible to integrate my Angular 4 component (a mail window widget application built with webpack) into a static website, ideally utilizing the <script> tag? I came across some blog articles, but they all mention using SystemJS while my app is ...

Remove a particular file from the collection

Can documents be deleted or removed from a collection using the graphical user interface (GUI)? ...

Element on webpage "Expands" When Scrolled into Visibility

After posting a question on Stack Overflow, I noticed discrepancies between the element dimensions reported by Chrome Inspector and Selenium WebDriver. While Chrome Inspector showed w = 979, h = 1961, Selenium returned dimensions of 979 and 1461 respective ...

Exploring Angular 10: Managing Two Promises in ngOnInit

I am currently working on integrating the Strava API into my Angular app. To summarize briefly: When a user clicks on a button to connect to Strava They are redirected to Strava for authentication (using PKCE) Strava then redirects back to my app with a ...

Disable infinite scrolling when a checkbox is clicked

Currently, I have implemented infinite scrolling on a table and it is functioning properly. <tbody infinite-scroll-disabled="myModule.isScrollingDisabled()" infinite-scroll="myModule.nextPage()" infinate-scroll-immediate-check="false" infinite-scroll-d ...

What is causing the unexpected behavior of deferred.resolve in the q manual?

I can't seem to grasp this concept and it might be a silly question. Let's analyze the code snippet below: function throwError() { throw Error("can't touch this."); } var def = q.defer(); def.promise.then( function() { co ...

Exploring Grunt (node): Ways to Display Available Tasks

While I am accustomed to using Rakefile, Cakefile, and Jakefile, each of them offered a convenient method for listing the tasks available. For example: jake -T jake db:dump # Dump the database jake db:load # Populate the database ...and so ...

Troubleshooting CodeIgniter's AJAX call functionality issue

I have been attempting to test AJAX functionality within CodeIgniter, but unfortunately, I haven't had any success so far. Can someone please point out where I might be making a mistake? Below is my test_page.php: <!DOCTYPE html> <head> ...