简体   繁体   中英

How do I connect my discriminators in mongoose to my parent document? Getting errors when trying to import data

I am making an ecommerce app and I'm trying to create 1 document, 'products' which has a schema inside for 'reviews' and 'fabrics'. Each product has more than 1 fabric and each fabric has its own set of sizes depending on the type of product (accessories, plus size, standard, etc.).

I am trying to use mongoose discriminators to make these nested inside the 'fabrics' array in the Product model.

I am getting error after error when attempting to import data, I have been changing the setup to try and make it work to no avail. I have read the discriminator documentation along with about 30 different posts on mongoose discriminators.

The error I'm getting in this setup is "TypeError: Product.path is not a function"

This is like the 15th different way I've attempted to connect the discriminators, all based on other posts which people seem to say have worked for them.

Any help would be greatly appreciated!

My current code is:


const reviewSchema = mongoose.Schema(
  {
    name: { type: String, required: true },
    rating: { type: String, required: true },
    comment: { type: String, required: true },
  },
  {
    timestamps: true,
  }
)

const fabricSchema = new mongoose.Schema({
  fabricId: { type: String, required: true },
  fabricImage: { type: String, required: true },
})

const Product = mongoose.model(
  'Product',
  new mongoose.Schema({
    user: {
      type: mongoose.Schema.Types.ObjectId,
      required: true,
      ref: 'User',
    },
    sku: {
      type: String,
      required: true,
    },
    name: {
      type: String,
      required: true,
    },
    image: {
      type: String,
      required: true,
    },
    category: {
      type: String,
      required: true,
    },
    fabricType: {
      type: String,
      required: true,
    },
    details: {
      type: String,
      required: true,
    },
    reviews: [reviewSchema],
    rating: {
      type: Number,
      required: true,
      default: 0,
    },
    numReviews: {
      type: Number,
      required: true,
      default: 0,
    },
    price: {
      type: Number,
      required: true,
    },
    wholesalePrice: {
      type: Number,
      required: true,
    },
    sale: {
      type: Object,
      required: true,

      onSale: {
        type: Boolean,
        required: true,
        default: false,
      },
      salePrice: { type: Number },
    },
    fabrics: [fabricSchema],
  })
)

const productType = Product.path('fabrics')

const standardProduct = productType.discriminator(
  'standardProduct',
  new mongoose.Schema({
    availableSizes: {
      xs: { type: Number, required: true, default: 0 },
      s: { type: Number, required: true, default: 0 },
      m: { type: Number, required: true, default: 0 },
      l: { type: Number, required: true, default: 0 },
      xl: { type: Number, required: true, default: 0 },
    },
  })
)

const plusSizeProduct = productType.discriminator(
  'plusSizeProduct',
  new mongoose.Schema({
    availableSizes: {
      oneX: { type: Number, required: true, default: 0 },
      twoX: { type: Number, required: true, default: 0 },
    },
  })
)

const accessoryProduct = productType.discriminator(
  'accessoryProduct',
  new mongoose.Schema({
    availableSizes: {
      os: { type: Number, required: true, default: 0 },
    },
  })
)

export { Product, standardProduct, plusSizeProduct, accessoryProduct }

I fixed my own issue after playing around with it some more (a lot more). Instead of calling the model and schema / discriminator and schema together, I separated them (even though that seems inconsequential from other people's 'fixes' on other sites / posts here). I also did some reorganizing just for my own sensibility for the data.

I also moved { discriminatorKey: 'kind' } to being nested in the fabricSchema (may have helped).

What seemed to have fixed it though, was after separation, I connected productSchema.path('fabrics').

The final version I used that imported data properly was:


/*const options = { discriminatorKey: 'kind', collection: 'products' }*/

const reviewSchema = mongoose.Schema(
  {
    name: { type: String, required: true },
    rating: { type: String, required: true },
    comment: { type: String, required: true },
  },
  {
    timestamps: true,
  }
)

const fabricSchema = new mongoose.Schema(
  {
    fabricId: { type: String, required: true },
    fabricImage: { type: String },
    itemImage: {
      type: String,
    },
    availableSizes: {
      type: Object,
      required: true,
    },
  },
  { discriminatorKey: 'kind' }
)

const productSchema = new mongoose.Schema({
  user: {
    type: mongoose.Schema.Types.ObjectId,
    required: true,
    ref: 'User',
  },
  sku: {
    type: String,
    required: true,
  },
  name: {
    type: String,
    required: true,
  },
  image: {
    type: String,
    required: true,
  },
  category: {
    type: String,
    required: true,
  },
  fabricType: {
    type: String,
    required: true,
  },
  details: {
    type: String,
    required: true,
  },
  price: {
    type: Number,
    required: true,
  },
  wholesalePrice: {
    type: Number,
    required: true,
  },
  onSale: {
    type: Boolean,
    required: true,
    default: false,
  },
  salePrice: {
    type: Number,
  },
  reviews: [reviewSchema],
  rating: {
    type: Number,
    required: true,
    default: 0,
  },
  numReviews: {
    type: Number,
    required: true,
    default: 0,
  },
  fabrics: [fabricSchema],
})

const fabricSizes = productSchema.path('fabrics')

const Product = mongoose.model('Product', productSchema)

// sub schemas

const standardSchema = new mongoose.Schema({
  availableSizes: {
    xs: { type: Number, required: true, default: 0 },
    s: { type: Number, required: true, default: 0 },
    m: { type: Number, required: true, default: 0 },
    l: { type: Number, required: true, default: 0 },
    xl: { type: Number, required: true, default: 0 },
  },
})

const plusSizeSchema = new mongoose.Schema({
  availableSizes: {
    oneX: { type: Number, required: true, default: 0 },
    twoX: { type: Number, required: true, default: 0 },
  },
})

const accessorySchema = new mongoose.Schema({
  availableSizes: {
    os: { type: Number, required: true, default: 0 },
  },
})

// discriminators

const standardProduct = fabricSizes.discriminator(
  'standardProduct',
  standardSchema
)

const plusSizeProduct = fabricSizes.discriminator(
  'plusSizeProduct',
  plusSizeSchema
)

const accessoryProduct = fabricSizes.discriminator(
  'accessoryProduct',
  accessorySchema
)

export { Product, standardProduct, plusSizeProduct, accessoryProduct }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM