Obtain a nested array of objects from Mongoose's Model.find() method and then make modifications to the inner array

I need to retrieve an array of objects with a specific ID from my database within a server route, and then update a property of an object within that array (rather than returning just the objectID, I want to return the Document as an object with the specified ID).

Below is the code I've written for this task:

        let orders = await Order.find({restaurant: restaurantID, status: 'PROCESSING'})

        for(let order of orders){   //iterate through all orders
            for(let element of order.dishes){     //iterate through order.dishes array (called 'element' since the array contains objects)
                let dish = await Dish.findOne({_id: element._id})
                element['dish'] = dish  //create new property for the dish object
                delete element._id      //remove the ID property since it already exists inside the element.dish object
            }
        }

Each order object within orders includes an array named dishes, which holds objects with the properties amount and an id. To make it more manageable for the frontend, I aim to remove the ID property, replacing it with a new property called 'dish', holding the referenced dish object.

The challenge lies in manipulating the content of the orders array. While inspecting orders by converting it to JSON and sending it in the response, I obtain a JSON array of order objects. However, when I implement the provided code snippet, it fails to alter anything within my orders.

During debugging, the elements within my for loops appear as follows:

EmbeddedDocument {__parentArray: Proxy, __index: 0, $__parent: model, $__: InternalCache, $isNew: false, …}
. Upon conversion to JSON, the desired output is achieved:
{"amount":1,"_id":"6183b84fec1c3e109a2271be"}
.

Is orders truly an array in this scenario? If not, what would be the most efficient way to manipulate it or obtain the documents as an array?

The following represents how orders appears while being monitored in the debug window:

price (get):ƒ () {\n        return this[getSymbol].call(this.$__[scopeSymbol] || this, path);\n      }
price (set):ƒ (v) {\n        this.$set.call(this.$__[scopeSymbol] || this, path, v);\n      }
restaurant (get):ƒ () {\n        return this[getSymbol].call(this.$__[scopeSymbol] || this, path);\n      }
restaurant (set):ƒ (v) {\n        this.$set.call(this.$__[scopeSymbol] || this, path, v);\n      }
status (get):ƒ () {\n        return this[getSymbol].call(this.$__[scopeSymbol] || this, path);\n      }
status (set):ƒ (v) {\n        this.$set.call(this.$__[scopeSymbol] || this, path, v);\n      }
timestamp (get):ƒ () {\n        return this[getSymbol].call(this.$__[scopeSymbol] || this, path);\n      }
timestamp (set):ƒ (v) {\n        this.$set.call(this.$__[scopeSymbol] || this, path, v);\n      }
user (get):ƒ () {\n        return this[getSymbol].call(this.$__[scopeSymbol] || this, path);\n      }
user (set):ƒ (v) {\n        this.$set.call(this.$__[scopeSymbol] || this, path, v);\n      }
__v (get):ƒ () {\n        return this[getSymbol].call(this.$__[scopeSymbol] || this, path);\n      }
__v (set):ƒ (v) {\n        this.$set.call(this.$__[scopeSymbol] || this, path, v);\n      }
__proto__:Model
length:1

In Postman, the response body looks similar to the desired format but only contains the id instead of the full dishes object:

[
    {
        "_id": "6183b84fec1c3e109a2271bd",
        "user": "6166bc426181646198fc483c",
        "restaurant": "6176947ce8b10986b018930e",
        "dishes": [
            {
                "amount": 1,
                "_id": "6183b84fec1c3e109a2271be"
            },
            {
                "amount": 2,
                "_id": "6183b84fec1c3e109a2271bf"
            }
        ],
        "price": 30,
        "status": "PROCESSING",
        "timestamp": "2021-11-04T10:39:11.800Z",
        "__v": 0
    }
]

If this issue has been addressed elsewhere, kindly share the link to the relevant question/answer. I have devoted several hours attempting to resolve this matter and have explored various questions without finding a suitable solution.

Answer №1

Many people often find themselves puzzled when they realize they can't change the data retrieved from MongoDB.

The reason behind this is Mongoose's peculiar behavior; instead of simple JSON, it returns a set of Mongoose objects. These objects come with additional methods like .save(), but most importantly, their nested objects are unchangeable. Simply modifying their properties will not have any impact.

To make modifications to the data returned by Mongoose, you have two options:

  1. Utilize .markModified()

It may seem strange at first, but changes made will only take effect once marked as modified. For example:

element['dish'] = dish;
order.save();

This alteration will not reflect in Mongo. You need to use .markModified():

element['dish'] = dish;
order.markModified("dishes");
order.save(); // It now works :|
  1. Instruct Mongoose to provide straightforward JSON output

By using .lean(), you can prevent Mongoose from creating its own objects and instead receive simple JSON data that can be modified freely.

let orders = await Order
           .find({restaurant: restaurantID, status: 'PROCESSING'})
           .lean()
           .exec(); // Don't forget to add .exec(), ensuring a true Promise is returned 

Additional tip: lean() offers better performance and efficiency.

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

Retrieve the parent document for every item within a Firebase collection group

Transitioning from an SQL background to document storage, I am currently navigating through a Firebase database structure that looks like this: John (doc) Restaurant Reviews (collection) Review 1 (doc) Review 2 (doc) Paul (doc) Restaurant Reviews ...

Harvesting the local image file

Currently, I have implemented a form that allows users to upload images and crop them. The process flow has been established as follows: 1. User uploads the image 2. Server processes the image and sends it back to the browser 3. User crops the image a ...

send back information obtained via an ajax request made by a javascript module

Here is a code snippet featuring an object with a function that makes an AJAX call. The function currently returns an empty array, but we need to figure out how to return the data after receiving the response. var receivedData = []; var AjaxUtil = { ...

How to adjust transparency in Three.js objects

Currently, I am developing a scene where certain elements are loaded from a JSON file. While I am able to toggle the visibility of each individual object, I now find myself wanting to adjust the opacity/transparency of an individual object. The objects in ...

"Converting a basic function into a promise for an AngularJS tutorial: How to handle the error message '

To help my colleagues understand AngularJS, I am creating a dummy exercise. In this example, I want to call a service that provides an Object Array to be passed into a Controller and assigned to a $scope variable (using information about the Beatles). Inst ...

The jQuery slider's next button is not functioning as intended

jQuery('#slider-container').bjqs({ 'animation' : 'slide', 'width' : 1060, 'height' : 500, 'showControls' : false, 'centerMarkers' : false, animationDuration: 500, rotationS ...

Struggling with running npm start

Attempting to use nodemon start with my index.js file, but I'm encountering an unknown issue causing it to fail. ...

Managing location markers with Google Maps API V3: Saving and removing locations

I encountered an issue while using GMAP V3. After realizing the need to save map changes in a database, I struggled to find a way to accomplish this task. Before attempting any workarounds, I thought it would be best to gather some ideas first. The communi ...

What's the best way to vertically center a div with a 100% width and a set padding-bottom on the screen?

I am struggling with positioning the following div on my webpage. .div { width:100%; padding-bottom:20%; background-color:blue; } <div class="div"></div> I have been searching for a solution to vertically center this responsive div on my web ...

Implementing icon display upon click in a Meteor application

Currently, I am in the process of developing an application using meteor and within one of the templates, I have the following code snippet. <h3> <b> <a class="viewed" href="/jobdetails/{{_id}}">{{title}}</a> </b> ...

Implementing a click event on header elements within a full calendar component in a React application

I'm currently integrating full calendar into my project. I need to implement click events on the header buttons such as prev, next, today, and others. This is how I've set up full calendar with the specified header buttons: <FullCalendar d ...

Preventing Users from Accessing a PHP Page: Best Practices

I'm currently focusing on a problem that involves restricting a user from opening a PHP page. The following is my JavaScript code: <script> $('input[id=f1email1]').on('blur', function(){ var k = $('inp ...

Working with Java to parse non-strict JSON data that does not have keys enclosed in quotes

I am currently facing the challenge of parsing a string in JSON format where keys are not enclosed in quotes. While I have successfully parsed this string in Javascript, I am struggling to find a Java API that can assist me with parsing. The APIs I have at ...

Merge two scripts together

I'm facing an issue with my frontend due to having two separate scripts in my Vue.js component class. How can I merge them into one cohesive script? If the problem stems from elsewhere, what could it be? <script> import GETUSER from "@/graphql/ ...

Definition of a class in Typescript when used as a property of an object

Currently working on a brief .d.ts for this library, but encountered an issue with the following: class Issuer { constructor(metadata) { // ... const self = this; Object.defineProperty(this, 'Client', { va ...

I am experiencing difficulty getting my component to properly implement the bootstrap NavBar and NavIcon styles

I am new to using bootstrap with react and I am facing an issue where the dimensions are not being applied to my Navbar and Navbar Icon. I have already installed dependencies and used className instead of class, but still no changes are visible. import Re ...

Optimizing Angular's ng-repeat for efficient updates by restricting the watch functionality to the relevant iteration

My task involves creating a table where users can edit certain fields in each row, which will impact other fields within the same row. Due to this requirement, I cannot use bind-once for all the rendered data. To address this issue, I attempted using the ...

Tips for stopping ajax requests from automatically following redirects in jQuery

When utilizing the jQuery ajax functions to connect with a web service, I encounter an issue where the server redirects the response to a page with a 200 status code instead of providing a proper status code indicating an error. Unfortunately, I am unable ...

The array containing JSON objects enclosed within curly braces is causing a syntax error

Given a variable containing data that looks like an "array" with JSON Objects inside (even though it is not actually formatted as an array, starting and ending with curly braces): {"x1","x2"},{"y1","y2"},{"z1","z2"} How can I transform this so that the i ...

Grouping various event listeners within a v-for loop

My Desired Outcome In my Vue component, I am displaying a list of actions using v-for. Each action should have a corresponding @click event handler that triggers the action method within the component. I need help declaring these actions in my data() fun ...