Mongoose 嵌入式文档、方法 "is not a function"
Mongoose Embedded Document, methods "is not a function"
在 Mongoose 中将 EmbeddedDoc 推送到另一个文档的过程中是否有任何原因会剥离该文档的方法?
我使用的脚本曾经有效,所以我不确定发生了什么变化。我知道他们在版本 5 的某个时候引入了 CoreMongooseArray,但我已经恢复到 5.0.7 的早期版本(使用普通数组),问题仍然存在。
我有一个在数组中嵌入购物车项目的购物车架构。购物车项目模式有各种静态和实例方法。在我将文档推入购物车文档之前,这些都是完全可用的。
在那一刻,该函数不再可访问,任何调用结果的错误消息都表明该函数不存在。
基本架构如下:
购物车架构
let mongoose = require('mongoose'),
Schema = mongoose.Schema;
let idvalidator = require('mongoose-id-validator');
let CartItemSchema = require('./CartItem');
let PromotionSchema = require('./Promotion');
let _ = require('lodash');
let CartSchema = new Schema({
customer_id: {
type: Schema.Types.ObjectId,
ref: 'User'
},
cartItems: [CartItemSchema],
customItems: [],
promotionItems: [{type: PromotionSchema, excludeIndexes: true}],
quantity: {
type: Number,
min: 0,
required: true,
default: 0
},
subtotal: {
type: Number,
min: 0,
required: true,
default: 0
},
subtotalWithoutTax:{
type: Number,
min: 0,
required: true,
default: 0
},
total: {
type: Number,
min: 0,
required: true,
default: 0
},
totalWithoutTax:{
type: Number,
min: 0,
required: true,
default: 0
}
},
{
timestamps: true,
id: false
}
);
CartSchema.index({ createdAt: 1 }, { expireAfterSeconds: 604800 });
CartSchema.virtual('discount').get(function(){
return _.round(this.subtotal - this.total, 2);
});
CartSchema.virtual('tax').get(function(){
return _.round(this.total - this.totalWithoutTax, 2);
});
CartSchema.set('toObject', {virtuals: true});
CartSchema.set('toJSON', {virtuals: true});
CartSchema.plugin(idvalidator);
module.exports = CartSchema;
购物车项目架构
let mongoose = require('mongoose'),
Schema = mongoose.Schema;
let idvalidator = require('mongoose-id-validator');
let SizeSchema = require('./Size');
let ProductExtraSchema = require('./ProductExtra');
let CartItemSchema = new Schema({
product_id: {
type: Schema.Types.ObjectId,
ref: 'Product',
required: true
},
sku: {
type: String,
required: true,
trim: true,
lowercase: true
},
name: {
type: String,
required: true,
trim: true
},
description: {
type: String,
trim: true,
alias: "desc"
},
price: {
type: Number,
min: 0,
required: true,
default: 0
},
priceWithoutTax:{
type: Number,
min: 0,
required: true,
default: 0
},
total: {
type: Number,
min: 0,
required: true,
default: 0
},
totalWithoutTax:{
type: Number,
min: 0,
required: true,
default: 0
},
taxable: {
type: Boolean,
required: true,
default: false
},
taxRate: {
type: Number,
required: true,
min: 0,
default: 0.2
},
quantity: {
type: Number,
min: 1,
required: true,
default: 1
},
size: SizeSchema,
extras: [ProductExtraSchema]
},
{
timestamps: true,
id: false
}
);
CartItemSchema.set('toObject', {virtuals: true});
CartItemSchema.set('toJSON', {virtuals: true});
CartItemSchema.plugin(idvalidator);
module.exports = CartItemSchema;
这些在单独的脚本中转换为模型,其中添加了静态模型和实例模型。
如果我随后执行以下操作,这些方法会在推送发生后立即消失:
let CartItem = require('../models/CartItem');
let Cart = require('../models/Cart');
let cartItem = CartItem.hydrate(req.body.cartItem);
let cart = new Cart();
console.log(cartItem.calculateTotals);
cart.cartItems.push(cartItem);
console.log(cart.cartItems[0].calculateTotals);
// Console.logs([Function])
// Console.logs(undefined)
更糟糕的是,我创建了一个非常基本的 mocha 测试,它基本上做了同样的事情并且成功了。那么区别是什么呢?
为什么一个成功而另一个不成功?
describe('test', function(){
it('should allow childs methods to be accessed', function(){
let childSchema = new Schema({
name: String
},
{
timestamps: true,
id: false
}
);
childSchema.methods.hyper = function(){
console.log("I've eaten too many sweets")
};
let parentSchema = new Schema({
name: String,
children: [childSchema],
},
{
timestamps: true,
id: false
}
);
let parent = mongoose.model('Parent', parentSchema);
let child = mongoose.model('Child', childSchema);
let c = child.hydrate({name: 'Sarah'});
let p = new parent({name: 'Joe'});
p.children.push(c);
for(let c of p.children){
c.hyper();
// Successfully logs "I've eaten too many sweets"
}
return true;
});
});
我设法使用以下 schema/model 设置顺序重现此内容:
- 创建
CartItemSchema
架构
- 创建
CartSchema
架构
- 创建
Cart
模型
- 将
calculateTotals
方法添加到 CartItemSchema
- 创建
CartItem
模型
第 4 步是罪魁祸首:您正在修改模型已经使用的模式(间接地,Cart
)。
正确的顺序(或者至少,应该产生最少问题的顺序)应该是:
- 创建
CartItemSchema
架构
- 将
calculateTotals
方法添加到 CartItemSchema
- 创建
CartItem
模型
- 创建
CartSchema
架构
- 创建
Cart
模型
在 Mongoose 中将 EmbeddedDoc 推送到另一个文档的过程中是否有任何原因会剥离该文档的方法?
我使用的脚本曾经有效,所以我不确定发生了什么变化。我知道他们在版本 5 的某个时候引入了 CoreMongooseArray,但我已经恢复到 5.0.7 的早期版本(使用普通数组),问题仍然存在。
我有一个在数组中嵌入购物车项目的购物车架构。购物车项目模式有各种静态和实例方法。在我将文档推入购物车文档之前,这些都是完全可用的。 在那一刻,该函数不再可访问,任何调用结果的错误消息都表明该函数不存在。
基本架构如下:
购物车架构
let mongoose = require('mongoose'),
Schema = mongoose.Schema;
let idvalidator = require('mongoose-id-validator');
let CartItemSchema = require('./CartItem');
let PromotionSchema = require('./Promotion');
let _ = require('lodash');
let CartSchema = new Schema({
customer_id: {
type: Schema.Types.ObjectId,
ref: 'User'
},
cartItems: [CartItemSchema],
customItems: [],
promotionItems: [{type: PromotionSchema, excludeIndexes: true}],
quantity: {
type: Number,
min: 0,
required: true,
default: 0
},
subtotal: {
type: Number,
min: 0,
required: true,
default: 0
},
subtotalWithoutTax:{
type: Number,
min: 0,
required: true,
default: 0
},
total: {
type: Number,
min: 0,
required: true,
default: 0
},
totalWithoutTax:{
type: Number,
min: 0,
required: true,
default: 0
}
},
{
timestamps: true,
id: false
}
);
CartSchema.index({ createdAt: 1 }, { expireAfterSeconds: 604800 });
CartSchema.virtual('discount').get(function(){
return _.round(this.subtotal - this.total, 2);
});
CartSchema.virtual('tax').get(function(){
return _.round(this.total - this.totalWithoutTax, 2);
});
CartSchema.set('toObject', {virtuals: true});
CartSchema.set('toJSON', {virtuals: true});
CartSchema.plugin(idvalidator);
module.exports = CartSchema;
购物车项目架构
let mongoose = require('mongoose'),
Schema = mongoose.Schema;
let idvalidator = require('mongoose-id-validator');
let SizeSchema = require('./Size');
let ProductExtraSchema = require('./ProductExtra');
let CartItemSchema = new Schema({
product_id: {
type: Schema.Types.ObjectId,
ref: 'Product',
required: true
},
sku: {
type: String,
required: true,
trim: true,
lowercase: true
},
name: {
type: String,
required: true,
trim: true
},
description: {
type: String,
trim: true,
alias: "desc"
},
price: {
type: Number,
min: 0,
required: true,
default: 0
},
priceWithoutTax:{
type: Number,
min: 0,
required: true,
default: 0
},
total: {
type: Number,
min: 0,
required: true,
default: 0
},
totalWithoutTax:{
type: Number,
min: 0,
required: true,
default: 0
},
taxable: {
type: Boolean,
required: true,
default: false
},
taxRate: {
type: Number,
required: true,
min: 0,
default: 0.2
},
quantity: {
type: Number,
min: 1,
required: true,
default: 1
},
size: SizeSchema,
extras: [ProductExtraSchema]
},
{
timestamps: true,
id: false
}
);
CartItemSchema.set('toObject', {virtuals: true});
CartItemSchema.set('toJSON', {virtuals: true});
CartItemSchema.plugin(idvalidator);
module.exports = CartItemSchema;
这些在单独的脚本中转换为模型,其中添加了静态模型和实例模型。
如果我随后执行以下操作,这些方法会在推送发生后立即消失:
let CartItem = require('../models/CartItem');
let Cart = require('../models/Cart');
let cartItem = CartItem.hydrate(req.body.cartItem);
let cart = new Cart();
console.log(cartItem.calculateTotals);
cart.cartItems.push(cartItem);
console.log(cart.cartItems[0].calculateTotals);
// Console.logs([Function])
// Console.logs(undefined)
更糟糕的是,我创建了一个非常基本的 mocha 测试,它基本上做了同样的事情并且成功了。那么区别是什么呢? 为什么一个成功而另一个不成功?
describe('test', function(){
it('should allow childs methods to be accessed', function(){
let childSchema = new Schema({
name: String
},
{
timestamps: true,
id: false
}
);
childSchema.methods.hyper = function(){
console.log("I've eaten too many sweets")
};
let parentSchema = new Schema({
name: String,
children: [childSchema],
},
{
timestamps: true,
id: false
}
);
let parent = mongoose.model('Parent', parentSchema);
let child = mongoose.model('Child', childSchema);
let c = child.hydrate({name: 'Sarah'});
let p = new parent({name: 'Joe'});
p.children.push(c);
for(let c of p.children){
c.hyper();
// Successfully logs "I've eaten too many sweets"
}
return true;
});
});
我设法使用以下 schema/model 设置顺序重现此内容:
- 创建
CartItemSchema
架构 - 创建
CartSchema
架构 - 创建
Cart
模型 - 将
calculateTotals
方法添加到CartItemSchema
- 创建
CartItem
模型
第 4 步是罪魁祸首:您正在修改模型已经使用的模式(间接地,Cart
)。
正确的顺序(或者至少,应该产生最少问题的顺序)应该是:
- 创建
CartItemSchema
架构 - 将
calculateTotals
方法添加到CartItemSchema
- 创建
CartItem
模型 - 创建
CartSchema
架构 - 创建
Cart
模型