Mongoose:
is a very good framework around MongoDB that make it easy to work with MongoDB because most of the things are managed internally by Mongoose. Populate Virtuals is part of the framework and then will allow you to have basic entity-relationship resolved at driver-level.
Aggregation Framework:
is a more advanced feature, you can think it as a query language (actually, it is) where you can create basic, medium, advanced query that are resolved at DB-level (this is huge difference in terms of performance). Rather than just "fetch" some data with $lookup, you can also filter the data or grouping by some key. Something you can't do with virtuals.
As general point, you can think Aggregation Framework as a very clean and extendible way to write performance oriented query in MongoDB since the whole pipeline is resolved at DB-level rather then driver-level.
NOTE:
Aggregation Expressions can be also used as part of findAndModify update pipeline, that means you can compute a find and update the data by using a pipeline (something you can't do with virtuals).
NOTE:
Upcoming version of MongoDB 4.4 will also introduce Aggregate Expressions in find(), that make the aggregate syntax a good investment for write you query.