From 6ee37a13fb5208ffb0b6c72b610c7eda39a0e443 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Wed, 26 Mar 2025 17:29:52 -0400 Subject: [PATCH 1/4] fix(populate): handle virtual populate on array of UUIDs Fix #15315 --- .../populate/assignRawDocsToIdStructure.js | 7 +++- test/model.populate.test.js | 42 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/helpers/populate/assignRawDocsToIdStructure.js b/lib/helpers/populate/assignRawDocsToIdStructure.js index 765d69f06af..67fa17f4c53 100644 --- a/lib/helpers/populate/assignRawDocsToIdStructure.js +++ b/lib/helpers/populate/assignRawDocsToIdStructure.js @@ -78,7 +78,12 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re continue; } - sid = String(id); + if (id?.constructor?.name === 'Binary' && id.sub_type === 4 && typeof id.toUUID === 'function') { + // Workaround for gh-15315 because Mongoose UUIDs don't use BSON UUIDs yet. + sid = String(id.toUUID()); + } else { + sid = String(id); + } doc = resultDocs[sid]; // If user wants separate copies of same doc, use this option if (options.clone && doc != null) { diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 110471823be..cb4430ba0d9 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -7,6 +7,7 @@ const start = require('./common'); const assert = require('assert'); +const { randomUUID } = require('crypto'); const utils = require('../lib/utils'); const util = require('./util'); const MongooseError = require('../lib/error/mongooseError'); @@ -11423,4 +11424,45 @@ describe('model: populate:', function() { await m.disconnect(); }); + + it('handles populating UUID fields (gh-15315)', async function() { + const categorySchema = new Schema({ + _id: { type: 'UUID', default: () => randomUUID() }, + name: { type: String, required: true }, + desc: { type: String, required: true } + }); + + categorySchema.virtual('announcements', { + ref: 'Announcement', + localField: '_id', + foreignField: 'categories' + }); + + const announcementSchema = new Schema({ + _id: { type: 'UUID', default: () => randomUUID() }, + title: { type: String, required: true }, + content: { type: String, required: true }, + validUntil: { type: Date, required: true }, + important: { type: Boolean, default: false }, + categories: [{ type: 'UUID', ref: 'Category' }] + }); + + const Category = db.model('Category', categorySchema); + const Announcement = db.model('Announcement', announcementSchema); + + const category = new Category({ name: 'Tech', desc: 'Technology News' }); + await category.save(); + + const announcement = new Announcement({ + title: 'New Tech Release', + content: 'Details about the new tech release', + validUntil: new Date(), + categories: [category._id] + }); + await announcement.save(); + + const populatedCategory = await Category.findOne({ _id: category._id }).populate('announcements'); + assert.strictEqual(populatedCategory.announcements.length, 1); + assert.strictEqual(populatedCategory.announcements[0].title, 'New Tech Release'); + }); }); From ff9d1e701b9e0d63efb14b1f0792c5f22fd0f7fa Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Mar 2025 10:50:04 -0400 Subject: [PATCH 2/4] Update test/model.populate.test.js Co-authored-by: hasezoey --- test/model.populate.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index cb4430ba0d9..1d89df5a207 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -11450,8 +11450,7 @@ describe('model: populate:', function() { const Category = db.model('Category', categorySchema); const Announcement = db.model('Announcement', announcementSchema); - const category = new Category({ name: 'Tech', desc: 'Technology News' }); - await category.save(); + const category = await Category.create({ name: 'Tech', desc: 'Technology News' }); const announcement = new Announcement({ title: 'New Tech Release', From dd44c374eb71de82c1394e677039ce173b973643 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Mar 2025 10:50:21 -0400 Subject: [PATCH 3/4] Update test/model.populate.test.js Co-authored-by: hasezoey --- test/model.populate.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 1d89df5a207..4da01c12962 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -11452,13 +11452,12 @@ describe('model: populate:', function() { const category = await Category.create({ name: 'Tech', desc: 'Technology News' }); - const announcement = new Announcement({ + const announcement = await Announcement.create({ title: 'New Tech Release', content: 'Details about the new tech release', validUntil: new Date(), categories: [category._id] }); - await announcement.save(); const populatedCategory = await Category.findOne({ _id: category._id }).populate('announcements'); assert.strictEqual(populatedCategory.announcements.length, 1); From ae3cc595418c1d89db1e19096efc25b2ecc37b0a Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Thu, 27 Mar 2025 11:02:34 -0400 Subject: [PATCH 4/4] fix lint --- test/model.populate.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/model.populate.test.js b/test/model.populate.test.js index 4da01c12962..0f38ce648bb 100644 --- a/test/model.populate.test.js +++ b/test/model.populate.test.js @@ -11452,7 +11452,7 @@ describe('model: populate:', function() { const category = await Category.create({ name: 'Tech', desc: 'Technology News' }); - const announcement = await Announcement.create({ + await Announcement.create({ title: 'New Tech Release', content: 'Details about the new tech release', validUntil: new Date(),