Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic Object ID reference for a subdocument inside an array #14249

Closed
vkarpov15 opened this issue Jan 11, 2024 Discussed in #14243 · 1 comment · Fixed by #14343
Closed

Dynamic Object ID reference for a subdocument inside an array #14249

vkarpov15 opened this issue Jan 11, 2024 Discussed in #14243 · 1 comment · Fixed by #14343
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@vkarpov15
Copy link
Collaborator

Discussed in #14243

Originally posted by echo-999 January 8, 2024
I'm trying to create a dynamic ref for an object ID stored inside a property of a subdocument. The property can reference multiple models (even models registered in a different mongoose database instance) so I use the model instance directly instead of a model name.

const subSchema = new Schema({
	category: String,
	ref: {
		type: Schema.Types.ObjectId,
		ref: function() {
			return this.category === 'catA' ? CategoryAModel : CategoryBModel // imports model instances
		}
	}
})

const parentSchema = new Schema({
	name: String,
	children: [subSchema]
})

const ParentModel = db.model('Parent', parentSchema)

As you can see, the ref property is the Object ID of either a document from CategoryAModel or CategoryBModel. I started creating documents for this model, such as the following:

const data = {
	name: 'Test Data',
	children: [
		{
			category: 'catA',
			ref: '658e9f1901f3da2c14920401' // <- existing document from CategoryAModel
		},
		{
			category: 'catB',
			ref: '654995e0c89d1c19c84e77b7' // <- existing document from CategoryBModel
		}
	]
}

But when i tried to populate this, the ref for category: 'catA' becomes null (despite existing). I logged the this context in the ref's ref function and saw that this refers to the document being processed (same shape as the data above), and that this.category is undefined because it's actually inside the children array. Essentially making the ref always result in being the CategoryBModel

Since it's an array, how would I go and make a dynamic reference? Is there a way to access the index of the subSchema being referred to?

@vkarpov15 vkarpov15 added this to the 8.0.5 milestone Jan 11, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.1.1, 8.1.2 Jan 23, 2024
@vkarpov15 vkarpov15 modified the milestones: 8.1.2, 8.1.3 Feb 8, 2024
@IslandRhythms IslandRhythms added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. and removed note to self labels Feb 8, 2024
@IslandRhythms
Copy link
Collaborator

IslandRhythms commented Feb 8, 2024

Populating both results in only catB being populated. If only one entry, it works as intended.

const mongoose = require('mongoose');

const { Schema } = mongoose;

const aSchema = new Schema({
  name: String
});

const bSchema = new Schema({
  name: String
});

const CategoryAModel = mongoose.model('CategoryAModel', aSchema);
const CategoryBModel = mongoose.model('CategoryBModel', bSchema);

const testSchema = new Schema({
  category: String,
  ref: {
    type: Schema.Types.ObjectId,
    ref: function() {
      return this.category === 'catA' ? CategoryAModel : CategoryBModel
    }
  }
});

const parentSchema = new Schema({
  name: String,
  children: [testSchema]
});

const Test = mongoose.model('Test', parentSchema);

async function run() {
  await mongoose.connect('mongodb://localhost:27017');
  await mongoose.connection.dropDatabase();

  const A = await CategoryAModel.create({
    name: 'A'
  });
  const B = await CategoryBModel.create({
    name: 'B'
  });

  const doc = await Test.create({
    name: 'Parent',
    children: [{ category: 'catA', ref: A._id }, { category: 'catB', ref: B._id }]
  });

  const res = await Test.findOne().populate('children.ref');
  console.log('what is res', res, res.children);
}

run();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants