Skip to content

Instantly share code, notes, and snippets.

@chalkpe
Last active April 28, 2021 08:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chalkpe/e1290de3d58ac2b997b675f6fe2db6c9 to your computer and use it in GitHub Desktop.
Save chalkpe/e1290de3d58ac2b997b675f6fe2db6c9 to your computer and use it in GitHub Desktop.
const mongoose = require('mongoose')
const User = mongoose.model('User', new mongoose.Schema({
name: String
}))
const Post = mongoose.model('Post', new mongoose.Schema({
title: String
}))
const Comment = mongoose.model('Comment', new mongoose.Schema({
content: String,
target: {
type: Schema.Types.ObjectId,
required: true,
refPath: 'targetModel'
},
targetModel: {
type: String,
required: true,
enum: ['User', 'Post']
}
}))
// populate dynamic reference via mongoose `refPath`
await Comment.find({ query }).populate('target').exec()
// populate dynamic reference via aggregation pipeline
const generatePipeline = ({ query, model, ref, refPath }) => [
{
$match: { ...query, [refPath]: model.modelName }
},
{
$lookup: {
from: model.collection.name,
foreignField: '_id',
localField: ref,
as: ref
}
},
{
$addFields: {
[ref]: { $arrayElemAt: [`$${ref}`, 0] }
}
}
]
await Comment.aggregate(
[User, Post].flatMap((model, index) => {
const pipeline = generatePipeline({ query, model, ref: 'target', refPath: 'targetModel' })
return index === 0 ? pipeline : [{ $unionWith: { coll: Comment.collection.name, pipeline } }]
})
).exec()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment