[求助] Nodejs Mongoose 数据类型的问题

[求助] Nodejs Mongoose 数据类型的问题

在mongoose中定义以下Schema:

var v = new Schema({
    name: { type: String },
    status: { type: Number }
});

然后在查询结果中想将Number类型的status字段替换成字符串返回:

model.find(function(datas) {
    datas.forEach(function(n){
        switch(n.status) {
            case 1: n.status = "正常"; break;
            case 2: n.status = "不正常"; break;
            default: n.status = "未知"; break;
        }
    })
    res.render("a", {data:datas});
});

但是,由于model里面定义的status字段类型是Number,所以导致这里遍历结果集修改字段为字符串不生效。

请教下这里应该怎么处理啊(PS:排除在view中进行处理的方法)


6 回复

在Mongoose中,如果你希望在查询结果中将status字段从数字转换为字符串,可以通过使用虚拟属性(virtuals)或者自定义getter来实现。下面是两种方法的示例:

方法一:使用虚拟属性(Virtuals)

虚拟属性允许你在模型中定义一个属性,但不会存储到数据库中。你可以通过这种方式定义一个名为statusStr的新属性,它会根据status字段的值动态生成。

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var schema = new Schema({
    name: { type: String },
    status: { type: Number }
});

// 定义虚拟属性
schema.virtual('statusStr')
    .get(function() {
        switch(this.status) {
            case 1: return "正常";
            case 2: return "不正常";
            default: return "未知";
        }
    });

var model = mongoose.model('MyModel', schema);

model.find({}, function(err, datas) {
    if (err) {
        console.error(err);
        return res.status(500).send("Error fetching data");
    }

    // 将数据渲染到视图
    res.render("a", { data: datas });
});

方法二:使用自定义getter

你也可以直接在模型上添加一个getter方法,这样当你访问status属性时,它会自动调用这个getter方法并返回对应的字符串。

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var schema = new Schema({
    name: { type: String },
    status: { type: Number }
});

// 添加getter
schema.path('status').get(function(statusNum) {
    switch(statusNum) {
        case 1: return "正常";
        case 2: return "不正常";
        default: return "未知";
    }
});

var model = mongoose.model('MyModel', schema);

model.find({}, function(err, datas) {
    if (err) {
        console.error(err);
        return res.status(500).send("Error fetching data");
    }

    // 将数据渲染到视图
    res.render("a", { data: datas });
});

这两种方法都可以实现将status字段从数字转换为字符串的目的,并且不需要在视图层进行额外处理。选择哪种方法取决于你的具体需求和个人偏好。


推荐你使用mongoose的Virtuals属性,参见http://mongoosejs.com/docs/guide.html

这是个localization的问题,确实是放在view中处理比较合理 此外,mongoose对String提供enum支持:

var v = new Schema({
    name: { type: String },
    status: { type: String, enum: ['normal', 'abnormal', 'unknown'] }
});

你这里修改status不成功原因是mongoose的查询返回的是mongoose的document对象,不要当成POJO处理,这是个大坑,一定要记住,很多莫名其妙的错误都来源于此

document可以用toObject转换成POJO对象

model.find(function(datas) {
    datas.forEach(function(n, index){
        n = n.toObject();
        switch(n.status) {
            case 1: n.status = "正常"; break;
            case 2: n.status = "不正常"; break;
            default: n.status = "未知"; break;
        }
        datas[index] = n;
    })
    res.render("a", {data:datas});
});

我尝试将结果集遍历重新赋值给另一个遍历,结果还是不行,我想到可能是由于mongoose返回的原因。 但是有点想不通的是,对于Javascript来说,应该就是Object类型,我通过输出发现结果接只是单纯的查询结果,如果是特殊的类型应该返回的是包含有一坨坨自定义原型的结构吧。

在Mongoose中,你可以使用virtuals来定义一个虚拟属性,这样可以在不影响数据库存储的情况下对数据进行转换。虚拟属性不会被保存到数据库中,但可以在查询结果中动态生成。

你可以通过添加一个虚拟属性来实现将 status 字段从数字转换为字符串。以下是具体步骤:

  1. 定义虚拟属性。
  2. 在虚拟属性上设置 get 方法来返回转换后的值。

以下是示例代码:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 定义Schema
var v = new Schema({
    name: { type: String },
    status: { type: Number }
});

// 添加虚拟属性statusStr
v.virtual('statusStr')
    .get(function() {
        switch(this.status) {
            case 1: return "正常";
            case 2: return "不正常";
            default: return "未知";
        }
    });

// 创建Model
var Model = mongoose.model('Model', v);

// 查询并渲染
Model.find()
    .then((datas) => {
        res.render("a", { data: datas });
    })
    .catch((err) => {
        console.error(err);
    });

在这个示例中,我们添加了一个名为 statusStr 的虚拟属性,并在其 get 方法中根据 status 字段的值返回相应的字符串。这样,在查询结果中可以通过 statusStr 获取到转换后的字符串,而无需在循环中手动修改 status 字段。

这样处理后,你在视图中可以直接使用 statusStr 属性来显示状态信息。

回到顶部