Skip to content

StrictModeError with embedded discriminator created with tiedValue argument #9108

@andreialecu

Description

@andreialecu

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

When using an embedded discriminator, schema validation seems to fail when using the tiedValue parameter when defining the discriminator.

If the current behavior is a bug, please provide the steps to reproduce.

"use strict";
const mongoose = require("mongoose");
const { Schema } = mongoose;
const assert = require("assert");

mongoose.set("debug", true);

run()
  .then(process.exit)
  .catch(console.error);

async function run() {
  await mongoose.connect(
    "mongodb://localhost:27017,localhost:27018,localhost:27019/test?replicaSet=rs",
    {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    },
  );

  await mongoose.connection.dropDatabase();
  var eventSchema = new Schema(
    { message: String },
    { discriminatorKey: "kind", _id: false },
  );

  var batchSchema = new Schema({ events: [eventSchema] });

  // `batchSchema.path('events')` gets the mongoose `DocumentArray`
  var docArray = batchSchema.path("events");

  // The `events` array can contain 2 different types of events, a
  // 'clicked' event that requires an element id that was clicked...
  var clickedSchema = new Schema(
    {
      element: {
        type: String,
        required: true,
      },
      elementArray: {
        type: [String],
        required: false,
      },
    },
    { _id: false },
  );
  // Make sure to attach any hooks to `eventSchema` and `clickedSchema`
  // **before** calling `discriminator()`.
  var Clicked = docArray.discriminator("Clicked", clickedSchema, "click");

  // ... and a 'purchased' event that requires the product that was purchased.
  var Purchased = docArray.discriminator(
    "Purchased",
    new Schema(
      {
        product: {
          type: String,
          required: true,
        },
      },
      { _id: false },
    ),
    "purchase",
  );

  var Batch = mongoose.model("EventBatch", batchSchema);

  // Create a new batch of events with different kinds
  var batch = {
    events: [
      { kind: "click", element: "#hero", message: "hello" },
      { kind: "purchase", product: "action-figure-1", message: "world" },
    ],
  };

  await Batch.create(batch);

  mongoose.set("debug", true);

  await Batch.updateOne(
    { events: { $elemMatch: { kind: "click", element: "#hero" } } },
    { "events.$.elementArray": ["test"] },
    { strict: "throw" }, // change to false and it works
  );

  const results = await Batch.find()
    .lean()
    .exec();
  console.dir(JSON.stringify(results), { depth: 1000 });
}

Results in error:

StrictModeError: Field `events.$.elementArray` is not in schema and strict mode is set to throw.

What is the expected behavior?

Should not throw, and should not need disabling strict mode. With the default strict setting of enabled, the update will just silently fail.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.

Mongoose 5.9.16

Note that without tiedValue it works properly as described here: #9093

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugWe've confirmed this is a bug in Mongoose and will fix it.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions