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,这块也不好用了,很奇怪,请先看上边的问题,下边这个异常情况,知道的话,也可以分享下经验


5 回复

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.doneproxy.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 版本可能会有不同的行为,确保版本兼容性。

  • 调试输出:检查每次赋值后的对象状态,以确保属性确实被正确赋值。

通过以上方法,你应该能够解决属性赋值问题。

回到顶部