Nodejs 关于给mongoose返回的json数据增加属性的问题

Nodejs 关于给mongoose返回的json数据增加属性的问题

Users.find(id, function (err, users) {
var i = 0;
for (; i < users.length; i += 1) {
users[i].name = ‘kk’;
}
console.log(users); //结果没有增加name这个属性
JSON.stringify(users); //结果也没有出现name
});

如果是修改属性就可以。 请问下为什么会出现这种情况呢?


10 回复

当然可以。在Node.js中使用Mongoose查询数据库后,直接修改返回的文档对象并不会持久化这些更改,因为Mongoose返回的对象只是原始数据的一个副本,并且这些更改并没有被保存到数据库中。如果你想要在返回的数据中增加一些额外的属性,你需要在将数据转换为JSON格式之前进行修改。

以下是修改后的代码示例:

const Users = require('./models/Users'); // 假设你已经定义了Users模型

Users.find({ id: someId }, function (err, users) {
    if (err) {
        console.error(err);
        return;
    }

    // 遍历每个用户并添加一个新属性
    const usersWithNewProperty = users.map(user => {
        user.name = 'kk'; // 添加或修改属性
        return user.toObject(); // 将Mongoose文档转换为普通JavaScript对象
    });

    console.log(usersWithNewProperty); // 输出带有新属性的对象数组
    console.log(JSON.stringify(usersWithNewProperty)); // 输出JSON字符串
});

解释

  1. user.toObject(): 当你从Mongoose模型中获取文档时,默认情况下它们是经过增强的JavaScript对象。这些对象具有额外的方法来帮助与数据库交互。通过调用toObject()方法,你可以将这些增强的对象转换成普通的JavaScript对象,这样就可以自由地添加或修改属性而不会影响底层的数据库文档。

  2. users.map(): 使用map函数遍历所有查询结果,并对每个用户对象应用相同的处理逻辑(在这里我们添加了一个名为name的新属性)。

  3. console.log: 最终打印出包含新属性的JavaScript对象数组以及它们的JSON表示形式。

这种方法确保了你可以在不改变数据库实际内容的情况下,向返回的JSON数据中添加自定义属性。


请调整下 Markdown 语法 http://www.bluesdream.com/blog/markdown-cheatsheet-syntax-manual.html

users 的数据是什么需要的说明一下… 确实很奇怪

console.log(users[0])结果贴上来看看。

mongoose查询出来的其实不是你的User Object,只是mongoosemodel,所以对它赋值没有任何用处。 理论上要这么玩:

User.find({age: 24}, function(error, users){
	console.log(users);
	users.forEach(function(user, index){
		user._doc.name = 'Test' + index;
	});
	console.log(users);
});

插个图.png

toObject()进行转换

哈哈,感谢大家的热情。我测试了下,3楼saionjisekai的方法是对的。谢谢。 6楼jiangli373的方法我也做了下,

Users.find(id, function (err, users) {
    var i = 0,
		mo = users.toObject();
    for (; i < mo.length; i += 1) {
        mo[i].name = 'kk';
    }
    console.log(mo); //结果显示增加了name这个属性
    console.log(JSON.stringify(mo));  //不显示任何数据,好像无法序列化的样子
});

请问:toObject()后的对象无法序列化,这又是怎么回事呢?

Users.find(id, function (err, users) {
	var data = users.map(function (user, id) {
		var mo = user.toObject();
		mo.name = 'kk';
		return mo;
	});
	console.log(data); //添加了name属性
	console.log(JSON.stringify(data)); //顺序序列化
});

toObject()是mongoose返回文档(user)的方法,不是文档数组(users)的方法…

厉害,我也遇到过这个问题,现在看到这些解决办法,再看看自己的傻办法。,早知道我了发个贴子问一下。 贴上我的方法

Users.find(id, function (err, users) {
    var data = users.map(function (user, id) {
        var mo = JSON.stringify(user);
		mo = JSON.parse(mo);
        mo.name = 'kk';
        return mo;
    });
    console.log(data); //添加了name属性
});

在Mongoose中,当你从数据库中查询到文档时,这些文档实际上是Mongoose的模型实例。直接修改这些实例的属性不会自动反映到原始的MongoDB文档上。这是因为Mongoose使用了一种叫做虚拟属性(virtual properties)的机制来处理这些情况。

你可以通过toObject()toJSON()方法将Mongoose文档转换为普通的JavaScript对象,然后在这个对象上添加新的属性。

下面是具体的实现方式:

Users.findById(id, function(err, user) {
    if (err) {
        console.error(err);
        return;
    }
    
    const userObj = user.toObject(); // 或者使用 user.toJSON()
    userObj.name = 'kk';

    console.log(userObj); // 输出带有新属性的对象
    console.log(JSON.stringify(userObj)); // 输出 JSON 字符串,包含新属性
});

解释

  • user.toObject()user.toJSON() 方法会把 Mongoose 文档转换成普通的 JavaScript 对象,这样你可以自由地添加或修改属性,并且这些改动会在序列化时反映出来。

  • 在你的例子中,users 是一个数组,所以你需要遍历这个数组并对每个元素调用 toObject()toJSON() 方法。

  • 如果你想要直接修改 Mongoose 文档的输出结果,可以在模型上定义虚拟属性(virtual properties),但这与直接添加新属性不同。

希望这可以帮助你解决遇到的问题!

回到顶部