mongoDB 在查询响应中返回 $numberDecimal

The*_*KER 7 mongoose mongodb node.js mongoose-schema

下面是我的猫鼬架构

const mongoose = require('mongoose');

const AccountingCostsSchema = mongoose.Schema(
    {
        // other properties goes here
        accountCosts: {
            type: mongoose.Decimal128,
            set: (v) =>
            mongoose.Types.Decimal128.fromString(parseFloat(v).toFixed(4)),
            required: true
        }
    },
    {
        collection: 'accountingCosts'
    }
);

export = mongoose.model('AccountingCosts', AccountingCostsSchema);
Run Code Online (Sandbox Code Playgroud)

MongoDB 中的数据

会计费用收取

文本模式视图中的数据

{
    "_id" : ObjectId("4e1eb38c2bdea2fb81f5e771"),
    "accountId" : ObjectId("4e8c1180d85de1704ce12110"),
    "accountCosts" : NumberDecimal("200.00"),
}
Run Code Online (Sandbox Code Playgroud)

文本模式视图中的数据

文本模式视图中的数据

我的查询

db.getCollection('accountingCosts').find({'accountId': '4e8c1180d85de1704ce12110'})
Run Code Online (Sandbox Code Playgroud)

查询结果

"accountCosts": {
      "$numberDecimal": "123.00"
}
Run Code Online (Sandbox Code Playgroud)

我尝试在模式上编写一个 getter 函数,就像我有一个 setter 函数一样。但它不起作用

get: function(value) {
      return value.toString();
}
Run Code Online (Sandbox Code Playgroud)

我的预期输出只是一个简单的属性,其名称和值如下所示

"accountCosts": "123.00"
Run Code Online (Sandbox Code Playgroud)

MrH*_*Him 15

我确信您找到了解决方案,但我也会在这里写下来,这样谁登陆这里就能找到解决方案。您使用 a 的想法getter是正确的,但也许您忘记在架构中启用它,所以让我们看看如何使用您的代码。

你有这个架构:

var AccountingCostsSchema = new Schema({
    accountId: String,
    accountCosts: {
        type: Schema.Types.Decimal128,
        default: 0
    }
});
Run Code Online (Sandbox Code Playgroud)

因此,当您检索它时,您将得到:

{
    "_id" : "12345",
    "accountId" : "123456",
    "accountCosts" : {
        "$numberDecimal": "123.00"
    }
}
Run Code Online (Sandbox Code Playgroud)

以您将得到的 accountCosts 作为数字为例,如下所示:

{
    "_id" : "12345",
    "accountId" : "123456",
    "accountCosts" : 123
}
Run Code Online (Sandbox Code Playgroud)

正如您所说,我们需要一个getter,所以我们需要在我们的模型文件中添加这个 getter 的函数,比如说在您的模式之后。这可能是你的 getter 函数:

function getCosts(value) {
    if (typeof value !== 'undefined') {
       return parseFloat(value.toString());
    }
    return value;
};
Run Code Online (Sandbox Code Playgroud)

现在,让我们在架构中声明这个 getter,它将变成:

var AccountingCostsSchema = new Schema({
    accountId: String,
    accountCosts: {
        type: Schema.Types.Decimal128,
        default: 0,
        get: getCosts
    }
});
Run Code Online (Sandbox Code Playgroud)

现在 mongoose 将了解您希望如何返回该值,但我们必须指定我们希望它使用 getter。因此,当我们想要以 json 格式检索值时,我们必须启用它。我们可以简单地添加它,如下所示:

var AccountingCostsSchema = new Schema({
    accountId: String,
    accountCosts: {
        type: Schema.Types.Decimal128,
        default: 0,
        get: getCosts
    }
}, {toJSON: {getters: true}});
Run Code Online (Sandbox Code Playgroud)

所以,当你检索它时,你会得到这个:

{
    "_id" : "12345",
    "accountId" : "123456",
    "accountCosts" : 123,
    "id" : "12345"
}
Run Code Online (Sandbox Code Playgroud)

但是,哇(这不是我的蝙蝠侠玻璃!)那是什么"id" : "12345"?根据猫鼬文件

默认情况下,Mongoose 为每个模式分配一个 id 虚拟 getter,该 getter 返回文档的 _id 字段转换为字符串,或者在 ObjectIds 的情况下,返回其十六进制字符串。如果您不希望将 id getter 添加到您的架构中,您可以通过在架构构建时传递此选项来禁用它。

我们怎样才能避免呢?我们只需添加id: false现在的架构即可:

var AccountingCostsSchema = new Schema({
    accountId: String,
    accountCosts: {
        type: Schema.Types.Decimal128,
        default: 0,
        get: getCosts
    },
    id: false
}, {toJSON: {getters: true}});
Run Code Online (Sandbox Code Playgroud)

现在你不会再看到它了。

最后一点提示(不,我还没有完成):如果您的模式中有一个像这样的对象数组,会发生什么?

var AccountingCostsSchema = new Schema({
    accountId: String,
    usersAndCosts: [{
        username: String,
        accountCosts: {
            type: Schema.Types.Decimal128,
            default: 0,
            get: getCosts
        }
    ],
    id: false
}, {toJSON: {getters: true}});
Run Code Online (Sandbox Code Playgroud)

现在有坏消息:您不能继续使用此模式。现在好消息:您可以轻松修复它。您需要为其创建一个新架构usersAndCosts,然后在父架构中引用它。让我们来看看它:

var usersAndCostsSchema = new Schema({
    username: String,
    accountCosts: {
        type: Schema.Types.Decimal128,
        default: 0,
        get: getCosts
    },
    id: false
}, {toJSON: {getters: true}});

var AccountingCostsSchema = new Schema({
    accountId: String,
    usersAndCosts: [usersAndCostsSchema],
    id: false
}, {toJSON: {getters: true}});
Run Code Online (Sandbox Code Playgroud)

结果是一样的,你的accountCosts将显示为数字,没有双重 ID。请记住,这当然是为了启用 getter,toJSON但您可能也需要启用它们toObject,因为您可能需要对 setter 执行相同的操作。但我们在这里讨论了 JSON 的 getter。