question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Embedded discriminators with "tiedValue" dont populate without explicitly specifing "model"

See original GitHub issue

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

What is the current behavior? When using Embedded discriminators with tiedValue instead of just name it doesn’t populate without also specifying model on populate call

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

// NodeJS: 16.1.0
// MongoDB: 4.2-bionic (Docker)
import * as mongoose from "mongoose"; // mongoose@5.12.7
import { inspect } from "util";
import { schemas } from "@typegoose/typegoose/lib/internal/data";

enum ActivityKind {
  Talk = "TALK",
  None = "NONE"
}

const GuestSchema = new mongoose.Schema({
  dummy: String
});

const ActivitySchema = new mongoose.Schema({
  title: String,
  kind: { required: true, type: String, enum: [ActivityKind.Talk] }
}, { discriminatorKey: "kind" });

const ActivityTalkSchema = new mongoose.Schema({
  speakers: [{ type: mongoose.Schema.Types.ObjectId, ref: "Guest" }]
});
ActivityTalkSchema.add(ActivitySchema);
// skip check because otherwise "add" can not be used
(ActivityTalkSchema.paths.kind as any).options.$skipDiscriminatorCheck = true;

const SponsorSchema = new mongoose.Schema({
  speakers: [{ type: mongoose.Schema.Types.ObjectId, ref: "Guest" }]
});

const ProgrammeSchema = new mongoose.Schema({
  sponsors: [SponsorSchema],
  activities: [{
    required: true,
    type: ActivitySchema
  }]
});
// @ts-expect-error mongoose does not have typings for "discriminator" without casting beforehand to DocumentArray
ProgrammeSchema.path("activities").discriminator("ActivityTalk", ActivityTalkSchema, ActivityKind.Talk);

const GuestModel = mongoose.model("Guest", GuestSchema);
const ProgrammeModel = mongoose.model("Programme", ProgrammeSchema);

(async () => {
  console.log(inspect(schemas.get("Activity"), false, 5));
  await mongoose.connect(`mongodb://localhost:27017/`, { useNewUrlParser: true, dbName: "verifyMASTER", useCreateIndex: true, useUnifiedTopology: true });

  // seed the database
  const guest1 = await GuestModel.create({ dummy: "1" });
  const guest2 = await GuestModel.create({ dummy: "2" });

  const programme1 = await ProgrammeModel.create({
    sponsors: [
      { speakers: [guest1, guest2] }
    ],
    activities: [
      { title: "hello", kind: ActivityKind.Talk, speakers: [guest1, guest2] }
    ]
  });

  const event = await ProgrammeModel.findOne({ _id: programme1._id }).orFail().exec();
  console.log("found", inspect(event, false, 5, true));
  await event.populate({ path: "activities.speakers" }).execPopulate();

  console.log("populate", inspect(event, false, 5, true));

  await mongoose.disconnect();
})();
{
    "compileOnSave": true,
    "typeAcquisition": {
        "enable": true
    },
    "compilerOptions": {
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "declarationMap": true,
        "outDir": "lib",
        "moduleResolution": "node",
        "target": "es6",
        "module": "commonjs",
        "newLine": "LF",
        "sourceMap": true,
        "removeComments": true,
        "strict": true,
        "allowUnreachableCode": false,
        "pretty": true,
        "declaration": true,
        "incremental": true,
        "tsBuildInfoFile": ".tsbuildinfo",
        "lib": [
            "esnext"
        ]
    },
    "include": [
        "src/**/*"
    ]
}

What is the expected behavior? to populate without also specifying model

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that “latest” is not a version. nodejs: 16.1.0 mongoose: 5.12.7 typescript: 4.2.4

PS: documentation taken from here

Note: populate work when not using tiedValue

PPS: if needed, there is also an reproduction repository with this code: https://github.com/typegoose/typegoose-testing/tree/verify537

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
IslandRhythmscommented, May 12, 2021
const mongoose = require('mongoose');
const util = require('util');
const {inspect} = util;
const {Schema} = mongoose;

const GuestSchema = new Schema ({
    dummy: String
});

const ActivitySchema = new Schema({
    title: String,
    kind: {required: true, type: String, enum: ["TALK"]}}, 
    {discriminatorKey: "kind"})

const ActivityTalkSchema = new Schema({
    speakers: [{type: mongoose.Schema.Types.ObjectId, ref: "Guest"}]
});

ActivityTalkSchema.add(ActivitySchema);

ActivityTalkSchema.paths.kind.options.$skipDiscriminatorCheck = true;

const SponsorSchema = new Schema({
    speakers: [{type: mongoose.Schema.Types.ObjectId, ref: "Guest"}]
});

const ProgrammeSchema = new Schema({
    sponsors: [SponsorSchema],
    activities: [{required: true, type: ActivitySchema}]
});

ProgrammeSchema.path("activities").discriminator("ActivityTalk", ActivityTalkSchema, "TALK");

const GuestModel = mongoose.model("Guest", GuestSchema);
const ProgrammeModel = mongoose.model("Programmer", ProgrammeSchema);

async function test() {
await mongoose.connect('mongodb://localhost:27017/', {
    useNewUrlParser: true,
    useCreateIndex: true,
    useUnifiedTopology: true
});

const guest1 = await GuestModel.create({dummy: "1"})
const guest2 = await GuestModel.create({dummy: "2"});

const programme1 = await ProgrammeModel.create({sponsors: [
    {speakers: [guest1, guest2]}
],
activities: [
    {title: "hello", kind: "TALK"}
]});

const event = await ProgrammeModel.findOne({_id: programme1._id}).orFail().exec();
console.log("found", inspect(event, false, 5, true));
await event.populate({path: "activities.speakers"}).execPopulate();
console.log("populate", inspect(event, false, 5, true));
await mongoose.disconnect();
}

test();

Output:

found {
  _id: 609c39bef31ef11ddcead82f,
  sponsors: [
    {
      speakers: [ 609c39bef31ef11ddcead82d, 609c39bef31ef11ddcead82e ],
      _id: 609c39bef31ef11ddcead830
    }
  ],
  activities: [
    {
      speakers: [],
      kind: 'TALK',
      _id: 609c39bef31ef11ddcead831,
      title: 'hello'
    }
  ],
  __v: 0
}
populate {
  _id: 609c39bef31ef11ddcead82f,
  sponsors: [
    {
      speakers: [ 609c39bef31ef11ddcead82d, 609c39bef31ef11ddcead82e ],
      _id: 609c39bef31ef11ddcead830
    }
  ],
  activities: [
    {
      speakers: [],
      kind: 'TALK',
      _id: 609c39bef31ef11ddcead831,
      title: 'hello'
    }
  ],
  __v: 0
}
1reaction
hasezoeycommented, May 12, 2021

just wanna add: this example is made with typescript, but should not be necessary to reproduce this issue - it is just for convenience

Read more comments on GitHub >

github_iconTop Results From Across the Web

What's New in Mongoose 4.12: Single Embedded Discriminators
Embedded discriminators gave you the ability to embed documents with different schemas in a single array. For example, let's say you have a ......
Read more >
Nested Discriminators - typegoose
There are currently multiple ways to define nested discriminators, which are: Directly and only the Class; A DiscriminatorObject (which is used in the...
Read more >
What's New in EF Core 7.0 - Microsoft Learn
The specific changes to make must be specified explicitly; they are not automatically detected by EF Core. Any tracked entities will not be ......
Read more >
Mongoose v6.8.2: API docs
Do not use this to create a new ObjectId instance, use mongoose. ... mongoose.model('Tree', schema); // setting schema options new Schema({ name: String...
Read more >
How to Develop a Conditional GAN (cGAN) From Scratch
Last Updated on September 1, 2020. Generative Adversarial Networks, or GANs, are an architecture for training generative models, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found