简体   繁体   English

mongoose - 从 Model.find() 获取对象的嵌套数组并操作内部数组

[英]mongoose - get a nested array of objects from Model.find() and manipulate the inner array

I am trying to get an array of objects with a certain ID from my database inside a route of my server, and then add change a property of an object inside the array (instead of returning an objectID to my client I want to return the Document as an object with the specific ID).我试图从我的服务器路由内的数据库中获取具有特定 ID 的对象数组,然后在数组中添加更改对象的属性(而不是将 objectID 返回给我的客户端,我想返回文档作为具有特定 ID 的对象)。

This is my code:这是我的代码:

        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
            }
        }

Every order object inside orders contains an array called dishes , which contains objects with the properties amount and an id . orders中的每个order对象都包含一个名为dishes的数组,该数组包含具有属性amountid Since my frontend can't do much with the ID, I want to delete the id property and add a new property called dish, which contains the dish object the id points to.由于我的前端无法对 ID 做太多事情,所以我想删除 id 属性并添加一个名为 disc 的新属性,该属性包含 id 指向的菜肴对象。

The problem I am facing is that I don't know how to manipulate the orders arrays content.我面临的问题是我不知道如何操作orders数组内容。 Whenever I parse orders to JSON and sent it inside my response, I recieve a JSON array of order objects just like I want to.每当我将orders解析为 JSON 并将其发送到我的响应中时,我就会收到一个订单对象的 JSON 数组,就像我想要的那样。 But when I add the code I pasted above, it does not change anything inside my orders.但是,当我添加上面粘贴的代码时,它不会更改我的订单中的任何内容。

Whenever I log the element inside my for loops it looks like this: EmbeddedDocument {__parentArray: Proxy, __index: 0, $__parent: model, $__: InternalCache, $isNew: false, …} but when I parse it to JSON I recieve exactely what I want, namely this: {"amount":1,"_id":"6183b84fec1c3e109a2271be"}每当我在 for 循环中记录元素时,它看起来像这样: EmbeddedDocument {__parentArray: Proxy, __index: 0, $__parent: model, $__: InternalCache, $isNew: false, …}但是当我将它解析为 JSON 我收到正是我想要的,即: {"amount":1,"_id":"6183b84fec1c3e109a2271be"}

Is orders even an array in this case?在这种情况下, orders甚至是一个数组吗? If not, what would be the easiest way to manipulate it/get the documents as an array?如果不是,那么操作它/将文档作为数组获取的最简单方法是什么?

This is what orders looks like when I watch it in my 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

And in postman, the res.body looks like this (almost exactely like it should but instead of the dishes object it contains only the id):在邮递员中, res.body 看起来像这样(几乎完全像它应该的那样,但它只包含 id 而不是菜肴对象):

[
    {
        "_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 was already solved, please send me a link to the question/answer.如果这已经解决了,请给我发送问题/答案的链接。 I spent the last few hours trying to solve this and I already looked at a lot of questions but none of the answers were helpful for me我花了最后几个小时试图解决这个问题,我已经看了很多问题,但没有一个答案对我有帮助

It is a common question.这是一个常见的问题。 People are often disconcerted because they can't alter the data coming from MongoDB.人们常常感到不安,因为他们无法更改来自 MongoDB 的数据。

The thing is, Mongoose is kind of weird;问题是,猫鼬有点奇怪; it does not return simple JSON, but constructs and returns a collection of Mongoose objects.它不返回简单的 JSON,而是构造并返回 Mongoose 对象的集合。 These objects have extra methods, like .save() , but above all their nested objects are immutable .这些对象有额外的方法,比如.save() ,但最重要的是它们的嵌套对象是不可变的 Simply changing their properties have no effect.简单地改变它们的属性是没有效果的。

In order to modify the data returned by Mongoose, you have two possibilities :为了修改Mongoose返回的数据,你有两种可能:

  1. Use .markModified()使用.markModified()

It's a really weird concept, but the changes you make won't be applied until you mark them as modified.这是一个非常奇怪的概念,但是您所做的更改在您将它们标记为已修改之前不会应用。 For instance :例如 :

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

This will have no effect.这不会有任何影响。 The name will remain unchanged in Mongo. Mongo 中的名称将保持不变。 You need .markModified() :你需要.markModified()

element['dish'] = dish;
order.markModified("dishes");
order.save(); // Works now :|
  1. Tell Mongoose to return simple JSON告诉猫鼬返回简单的 JSON

You can prevent Mongoose from constructing its own objects by using .lean() .您可以使用.lean()阻止 Mongoose 构建自己的对象。 this will return simple JSON data that can be tampered with at will.这将返回可以随意篡改的简单 JSON 数据。

let orders = await Order
           .find({restaurant: restaurantID, status: 'PROCESSING'})
           .lean()
           .exec(); // Also add .exec(), it returns a true Promise and not a thenable 

Bonus : lean() is faster and lighter.奖励: lean()更快更轻。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM