Nodejs mongoose检索出来的model,属性赋值问题
Nodejs mongoose检索出来的model,属性赋值问题
用mongoose检索出来一个model 比如 var modelA= mongoose.findOne(…); modelA没有属性test 直接用modelA.test={obeject};(一个json对象赋值) 然后再取modelA.test,就取不到
但还有特殊情况,用CNODE的开源代码 topics_id.forEach(function (id, i) { exports.getTopicById(id, proxy.done(function (topic, tags, author, last_reply) { topic.tags = tags; topic.author = author; //topic没有author属性 topic.reply = last_reply; topic.friendly_create_at = Util.format_date(topic.create_at, true); topic.friendly_short_create_at = Util.format_short_date(topic.create_at, true); topics[i] = topic;
console.log(author);
console.log(topic.author);
proxy.emit('topic_ready');
}));
});
这个代码之前好用,我升级了下mongoose,有其它一部分类似的代码不好用了,但这个仍然好用 今天我又升级了mongodb,这块也不好用了,很奇怪,请先看上边的问题,下边这个异常情况,知道的话,也可以分享下经验
Nodejs Mongoose 检索出来的 Model 属性赋值问题
问题描述
在使用 Mongoose 查询数据后,尝试直接为查询结果添加或修改属性时,可能会遇到一些问题。例如,当你使用 findOne
方法查询一个文档并尝试为其添加一个新的属性,却发现该属性无法正常赋值。
示例代码
假设我们有一个简单的 Mongoose 模型定义如下:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: String,
email: String
});
const User = mongoose.model('User', UserSchema);
// 假设数据库中存在一个名为 'John Doe' 的用户
现在我们尝试查询这个用户,并给它添加一个新属性 test
:
async function findUser() {
const user = await User.findOne({ name: 'John Doe' });
if (user) {
user.test = { object: 'value' };
console.log(user.test); // 输出: undefined
}
}
findUser();
在这个例子中,user.test
会输出 undefined
,即使我们已经尝试给它赋值。
解释
Mongoose 在查询数据后返回的对象是一个经过代理处理的实例,用于自动处理数据的持久化。直接为这些实例添加属性可能不会按预期工作,因为这些属性不会被自动保存到数据库中。
解决方案
如果你需要向查询结果添加新的属性,建议使用 set
方法或者直接操作原始的 JavaScript 对象。例如:
async function findUser() {
const user = await User.findOne({ name: 'John Doe' });
if (user) {
user.set('test', { object: 'value' });
console.log(user.test); // 输出: { object: 'value' }
}
}
findUser();
或者将 Mongoose 实例转换为普通 JavaScript 对象:
async function findUser() {
const user = await User.findOne({ name: 'John Doe' }).lean().exec();
if (user) {
user.test = { object: 'value' };
console.log(user.test); // 输出: { object: 'value' }
}
}
findUser();
特殊情况
在你的代码片段中,topics_id.forEach
循环中的代码似乎能够正常工作,这可能是因为你使用了 proxy.done
和 proxy.emit
方法来确保异步操作的完成。但是,如果升级了 Mongoose 或 MongoDB 后出现问题,可以尝试上述方法来确保属性赋值的正确性。
希望这些信息能帮助你解决属性赋值的问题。
mongoose是要定义schema的,增加字段,只能先这样:
schema.add({ test: mongoose.Schema.Types.Mixed })
谢谢回答,目前问题已经解决了,null的原因,是因为我两个不同的,数据合并后有冲突,导致部分数据检索出来是NULL,赋值出现问题。
PS,以上赋值方式可行
两个不同的数据库
当你使用 Mongoose 检索出一个 Model 实例时,如果尝试直接赋值一个新的属性(例如 test
),可能并不会按预期那样工作。这是因为 Mongoose 会对 Model 的属性进行一些特殊的处理,包括虚拟属性、getters 和 setters 等。
示例代码解释
1. 基本赋值
当你检索出一个 Model 实例后,如果你想要添加一个新的属性,需要确保该属性是可直接赋值的:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// 定义一个简单的 schema
const UserSchema = new Schema({
name: String,
age: Number
});
const User = mongoose.model('User', UserSchema);
// 检索数据
User.findOne({}).then(user => {
if (!user) return console.log('No user found');
// 直接赋值
user.test = { object: 'data' };
console.log(user.test); // 输出: { object: 'data' }
});
2. 特殊情况
在你的例子中,你提到 topics_id.forEach
循环中的代码在升级 Mongoose 和 MongoDB 后出现问题。这可能是因为某些 Mongoose 版本对嵌套文档或虚拟属性的行为有所改变。
假设 getTopicById
是一个异步函数,它返回一个已填充的对象:
function getTopicById(id, callback) {
// 模拟异步操作
setTimeout(() => {
const topic = {
id: id,
create_at: Date.now(),
tags: [],
author: null
};
callback(topic, [], {}, {});
}, 100);
}
topics_id.forEach((id, i) => {
exports.getTopicById(id, proxy.done((topic, tags, author, last_reply) => {
topic.tags = tags;
topic.author = author; // 直接赋值给 topic.author
topic.reply = last_reply;
topic.friendly_create_at = Util.format_date(topic.create_at, true);
topic.friendly_short_create_at = Util.format_short_date(topic.create_at, true);
topics[i] = topic;
console.log(author);
console.log(topic.author);
proxy.emit('topic_ready');
}));
});
解决方法
-
确保属性存在:在赋值前确保属性已经存在。你可以使用
Object.defineProperty
来定义新的属性。 -
检查 Mongoose 版本:不同的 Mongoose 版本可能会有不同的行为,确保版本兼容性。
-
调试输出:检查每次赋值后的对象状态,以确保属性确实被正确赋值。
通过以上方法,你应该能够解决属性赋值问题。