猫鼬嵌入式文档,方法“不是函数”

时间:2018-11-04 14:11:14

标签: mongodb mongoose mongoose-schema

将嵌入式文档推入Mongoose中的另一个文档的过程有什么理由会剥夺该文档的方法吗?

我使用的脚本曾经可以工作,所以我不确定发生了什么变化。我知道他们在版本5中的某个时候引入了CoreMongooseArray,但是我已经恢复到5.0.7的早期版本(使用常规数组),并且问题仍然存在。

我有一个Cart模式,该模式将Cart Items嵌入一个数组中。购物车商品模式具有各种静态和实例方法。这些文件在我将文档推入购物车文档之前一直都可以使用。 那时该功能不再可用,任何尝试调用结果的错误消息均表明该功能不存在。

以下是基本架构:

购物车模式

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)

更糟糕的是,我创建了一个非常基本的摩卡测试,该测试本质上是相同的,并且成功了。那么区别是什么呢? 为什么一个成功,另一个却不成功?

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;

    });

});

1 个答案:

答案 0 :(得分:1)

我设法按照以下模式/模型设置顺序重现了这一点:

  1. 创建CartItemSchema模式
  2. 创建CartSchema模式
  3. 创建Cart模型
  4. calculateTotals方法添加到CartItemSchema
  5. 创建CartItem模型

第4步是罪魁祸首:您正在修改已经由模型(间接由Cart使用)的模式。

正确的顺序(或至少发出最少数量问题的顺序)应为:

  1. 创建CartItemSchema模式
  2. calculateTotals方法添加到CartItemSchema
  3. 创建CartItem模型
  4. 创建CartSchema模式
  5. 创建Cart模型