Javascript mongoose在数据库中插入十进制128数据,保存为所需嵌套文档的字符串

Javascript mongoose在数据库中插入十进制128数据,保存为所需嵌套文档的字符串,javascript,node.js,mongodb,mongoose,decimal,Javascript,Node.js,Mongodb,Mongoose,Decimal,对于此示例: 数据集books.json文件: [ { "addr": "address1", "book": "book1", "rawPrice": "9.135027", "prices": [ {"net": "9.13502

对于此示例:
数据集
books.json
文件:

  [
    {
        "addr": "address1",
        "book": "book1",
        "rawPrice": "9.135027",
        "prices": [
          {"net": "9.135027"},
          {"gross": "10.15003"}
        ],
        "price": {
          "net": "9.135027",
          "gross": "10.15003"
        }
    },
    {
        "addr": "address2",
        "book": "book1",
        "rawPrice": "19.351017",
        "prices": [
          {"net": "19.351017"},
          {"gross": "21.50113"}
        ],
        "price": {
          "net": "19.351017",
          "gross": "21.50113"
        }
    }
  ]
import { readFileSync } from 'fs';
import { model, connect, Schema } from 'mongoose';

const uri = 'mongodb://localhost:27017/db-tests';

const log = (data: any) => console.log(JSON.stringify(data, null, 2));
const data = readFileSync('./books.json', { encoding:'utf8', flag:'r' });
const decimalField = {
  default: 0,
  required: true,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString(),
};
const decimalOptionalField = {
  default: 0,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString(),
};
const booksScema = new Schema(
  {
    addr: { $type: String },
    book: { $type: String },
    rawPrice: decimalField,
    price: {
      required: true,
      type: {
        net: decimalField,
        gross: decimalField,
      },
    },
    prices: {
      required: true,
      type: [
        {
          net: decimalOptionalField,
          gross: decimalOptionalField,
        }
      ],
    },
  },
  { timestamps: true, versionKey: false }
);

connect(uri, { useNewUrlParser: true, useUnifiedTopology: true }).then((mongoose) => {
  const booksModel = model('books', booksScema);
  booksModel.insertMany(JSON.parse(data)).then((insertedData) => {
    log(insertedData);
    mongoose.connection.close();
  });
});
插入代码
app.ts
文件:

  [
    {
        "addr": "address1",
        "book": "book1",
        "rawPrice": "9.135027",
        "prices": [
          {"net": "9.135027"},
          {"gross": "10.15003"}
        ],
        "price": {
          "net": "9.135027",
          "gross": "10.15003"
        }
    },
    {
        "addr": "address2",
        "book": "book1",
        "rawPrice": "19.351017",
        "prices": [
          {"net": "19.351017"},
          {"gross": "21.50113"}
        ],
        "price": {
          "net": "19.351017",
          "gross": "21.50113"
        }
    }
  ]
import { readFileSync } from 'fs';
import { model, connect, Schema } from 'mongoose';

const uri = 'mongodb://localhost:27017/db-tests';

const log = (data: any) => console.log(JSON.stringify(data, null, 2));
const data = readFileSync('./books.json', { encoding:'utf8', flag:'r' });
const decimalField = {
  default: 0,
  required: true,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString(),
};
const decimalOptionalField = {
  default: 0,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString(),
};
const booksScema = new Schema(
  {
    addr: { $type: String },
    book: { $type: String },
    rawPrice: decimalField,
    price: {
      required: true,
      type: {
        net: decimalField,
        gross: decimalField,
      },
    },
    prices: {
      required: true,
      type: [
        {
          net: decimalOptionalField,
          gross: decimalOptionalField,
        }
      ],
    },
  },
  { timestamps: true, versionKey: false }
);

connect(uri, { useNewUrlParser: true, useUnifiedTopology: true }).then((mongoose) => {
  const booksModel = model('books', booksScema);
  booksModel.insertMany(JSON.parse(data)).then((insertedData) => {
    log(insertedData);
    mongoose.connection.close();
  });
});
结果在数据库中插入如下数据:

[
  {
    "_id" : ObjectId("60006333e861c6c0b10778be"),
    "rawPrice" : NumberDecimal("9.135027"),
    "prices" : [ 
      {
        "net" : NumberDecimal("9.135027"),
        "_id" : ObjectId("60006333e861c6c0b10778bf")
      }, 
      {
        "gross" : NumberDecimal("10.15003"),
        "_id" : ObjectId("60006333e861c6c0b10778c0")
      }
    ],
    "price" : {
      "net" : "9.135027",
      "gross" : "10.15003"
    },
    "createdAt" : ISODate("2021-01-14T15:28:51.810Z"),
    "updatedAt" : ISODate("2021-01-14T15:28:51.810Z")
  }
  {
    "_id" : ObjectId("60006333e861c6c0b10778c1"),
    "rawPrice" : NumberDecimal("19.351017"),
    "prices" : [ 
      {
        "net" : NumberDecimal("19.351017"),
        "_id" : ObjectId("60006333e861c6c0b10778c2")
      }, 
      {
        "gross" : NumberDecimal("21.50113"),
        "_id" : ObjectId("60006333e861c6c0b10778c3")
      }
    ],
    "price" : {
      "net" : "19.351017",
      "gross" : "21.50113"
    },
    "createdAt" : ISODate("2021-01-14T15:28:51.812Z"),
    "updatedAt" : ISODate("2021-01-14T15:28:51.812Z")
  }
]
price: {
  net: decimalOptionalField,
  gross: decimalOptionalField,
},
const decimalField = {
  default: 0,
  required: true,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString(),
};
const decimalOptionalField = {
  default: 0,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString()
};
const booksScema = new Schema(
  {
    addr: String,
    book: String ,
    rawPrice: decimalField,
    price: {
      required: true,
      type: {
        net: decimalField,
        gross: decimalField,
      },
    },
    prices: {
      required: true,
      type: [
        {
          net: decimalOptionalField,
          gross: decimalOptionalField,
        }
      ],
    },
  },
  {
    timestamps: true,
    versionKey: false,
    typePojoToMixed: false,
  }
);

如结果所示,
rawPrice
prices
字段具有类型为
Decimal128
的正确值,但对于嵌套文档
price
的类型不正确,值保存为字符串。 但是,如果在模式中定义了价格,而没有如下详细对象:

[
  {
    "_id" : ObjectId("60006333e861c6c0b10778be"),
    "rawPrice" : NumberDecimal("9.135027"),
    "prices" : [ 
      {
        "net" : NumberDecimal("9.135027"),
        "_id" : ObjectId("60006333e861c6c0b10778bf")
      }, 
      {
        "gross" : NumberDecimal("10.15003"),
        "_id" : ObjectId("60006333e861c6c0b10778c0")
      }
    ],
    "price" : {
      "net" : "9.135027",
      "gross" : "10.15003"
    },
    "createdAt" : ISODate("2021-01-14T15:28:51.810Z"),
    "updatedAt" : ISODate("2021-01-14T15:28:51.810Z")
  }
  {
    "_id" : ObjectId("60006333e861c6c0b10778c1"),
    "rawPrice" : NumberDecimal("19.351017"),
    "prices" : [ 
      {
        "net" : NumberDecimal("19.351017"),
        "_id" : ObjectId("60006333e861c6c0b10778c2")
      }, 
      {
        "gross" : NumberDecimal("21.50113"),
        "_id" : ObjectId("60006333e861c6c0b10778c3")
      }
    ],
    "price" : {
      "net" : "19.351017",
      "gross" : "21.50113"
    },
    "createdAt" : ISODate("2021-01-14T15:28:51.812Z"),
    "updatedAt" : ISODate("2021-01-14T15:28:51.812Z")
  }
]
price: {
  net: decimalOptionalField,
  gross: decimalOptionalField,
},
const decimalField = {
  default: 0,
  required: true,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString(),
};
const decimalOptionalField = {
  default: 0,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString()
};
const booksScema = new Schema(
  {
    addr: String,
    book: String ,
    rawPrice: decimalField,
    price: {
      required: true,
      type: {
        net: decimalField,
        gross: decimalField,
      },
    },
    prices: {
      required: true,
      type: [
        {
          net: decimalOptionalField,
          gross: decimalOptionalField,
        }
      ],
    },
  },
  {
    timestamps: true,
    versionKey: false,
    typePojoToMixed: false,
  }
);

我得到了正确的结果:

[
  {
    "_id" : ObjectId("600064b60d223c13635a22dd"),
    "price" : {
      "net" : NumberDecimal("9.135027"),
      "gross" : NumberDecimal("10.15003")
    },
    "rawPrice" : NumberDecimal("9.135027"),
    "prices" : [ 
      {
        "net" : NumberDecimal("9.135027"),
        "gross" : NumberDecimal("0"),
        "_id" : ObjectId("600064b60d223c13635a22de")
      }, 
      {
        "net" : NumberDecimal("0"),
        "gross" : NumberDecimal("10.15003"),
        "_id" : ObjectId("600064b60d223c13635a22df")
      }
    ],
    "createdAt" : ISODate("2021-01-14T15:35:18.452Z"),
    "updatedAt" : ISODate("2021-01-14T15:35:18.452Z")
  },
  {
    "_id" : ObjectId("600064b60d223c13635a22e0"),
    "price" : {
      "net" : NumberDecimal("19.351017"),
      "gross" : NumberDecimal("21.50113")
    },
    "rawPrice" : NumberDecimal("19.351017"),
    "prices" : [ 
      {
        "net" : NumberDecimal("19.351017"),
        "gross" : NumberDecimal("0"),
        "_id" : ObjectId("600064b60d223c13635a22e1")
      }, 
      {
        "net" : NumberDecimal("0"),
        "gross" : NumberDecimal("21.50113"),
        "_id" : ObjectId("600064b60d223c13635a22e2")
      }
    ],
    "createdAt" : ISODate("2021-01-14T15:35:18.454Z"),
    "updatedAt" : ISODate("2021-01-14T15:35:18.454Z")
  }
]
但我需要该字段为必填项。

因此,我如何确保将值保存为小数128,同时也将其设置为必需值?

您的模式与数据集之间存在问题,并且您在Mongoose 5+中遇到异常,
price
变为
混合路径

首先,检查您是否需要。这两样你都试过了。如果我们假设您希望得到与
prices
(嵌套文档)中相同的结果,那么您的模式将如下所示

const decimalField = {
  default: 0,
  required: true,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString(),
};

const priceSchema = new Schema({
  net: decimalField,
  gross: decimalField,
});

const booksScema = new Schema(
  {
    addr: String,
    book: String ,
    rawPrice: decimalField,
    price: priceSchema,
    prices: {
      type: priceSchema,
      validate: (v: any) => Array.isArray(v) && v.length > 0,
    },
  },
  {
    timestamps: true,
    versionKey: false,
    // useNestedStrict: true, https://mongoosejs.com/docs/guide.html#useNestedStrict
    // strict: 'throw',
  }
);
或者您可以使用选项
typepojotomix:false
如下:

[
  {
    "_id" : ObjectId("60006333e861c6c0b10778be"),
    "rawPrice" : NumberDecimal("9.135027"),
    "prices" : [ 
      {
        "net" : NumberDecimal("9.135027"),
        "_id" : ObjectId("60006333e861c6c0b10778bf")
      }, 
      {
        "gross" : NumberDecimal("10.15003"),
        "_id" : ObjectId("60006333e861c6c0b10778c0")
      }
    ],
    "price" : {
      "net" : "9.135027",
      "gross" : "10.15003"
    },
    "createdAt" : ISODate("2021-01-14T15:28:51.810Z"),
    "updatedAt" : ISODate("2021-01-14T15:28:51.810Z")
  }
  {
    "_id" : ObjectId("60006333e861c6c0b10778c1"),
    "rawPrice" : NumberDecimal("19.351017"),
    "prices" : [ 
      {
        "net" : NumberDecimal("19.351017"),
        "_id" : ObjectId("60006333e861c6c0b10778c2")
      }, 
      {
        "gross" : NumberDecimal("21.50113"),
        "_id" : ObjectId("60006333e861c6c0b10778c3")
      }
    ],
    "price" : {
      "net" : "19.351017",
      "gross" : "21.50113"
    },
    "createdAt" : ISODate("2021-01-14T15:28:51.812Z"),
    "updatedAt" : ISODate("2021-01-14T15:28:51.812Z")
  }
]
price: {
  net: decimalOptionalField,
  gross: decimalOptionalField,
},
const decimalField = {
  default: 0,
  required: true,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString(),
};
const decimalOptionalField = {
  default: 0,
  type: Schema.Types.Decimal128,
  get: (v: Schema.Types.Decimal128) => v.toString()
};
const booksScema = new Schema(
  {
    addr: String,
    book: String ,
    rawPrice: decimalField,
    price: {
      required: true,
      type: {
        net: decimalField,
        gross: decimalField,
      },
    },
    prices: {
      required: true,
      type: [
        {
          net: decimalOptionalField,
          gross: decimalOptionalField,
        }
      ],
    },
  },
  {
    timestamps: true,
    versionKey: false,
    typePojoToMixed: false,
  }
);


感谢您的链接,我最终使用了
typepojotomix:false
选项,它看起来比为每个嵌套字段创建新模式更简单。