Mongoose Embedded Document, методы "не является функцией" - PullRequest
0 голосов
/ 04 ноября 2018

Есть ли причина, по которой процесс вставки EmbeddedDoc в другой документ в Mongoose лишил бы указанный документ его методов?

Используемый мной скрипт используется, поэтому я не уверен, что изменилось. Я знаю, что они внедрили CoreMongooseArray в какой-то момент в версии 5, но я вернулся к более ранней версии 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)

Чтобы усугубить ситуацию, я создал очень простой тест мокко, который по сути делает то же самое и успешно. Так в чем же разница? Почему один добивается успеха, а другой нет?

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 голосов
/ 04 ноября 2018

Мне удалось воспроизвести это, используя следующий порядок настройки схемы / модели:

  1. создать схему CartItemSchema
  2. создать схему CartSchema
  3. создать Cart модель
  4. добавить calculateTotals методы к CartItemSchema
  5. создать CartItem модель

Шаг № 4 является виновником: вы изменяете схему, которая уже используется моделью (косвенно, Cart).

Правильный порядок (или, по крайней мере, порядок, который должен давать наименьшее количество проблем) должен быть:

  1. создать схему CartItemSchema
  2. добавить calculateTotals методы к CartItemSchema
  3. создать CartItem модель
  4. создать схему CartSchema
  5. создать Cart модель
...