'Mongoose - "Enriched" Query with Data from other Collection

I'm quite new to using Mongoose and therefore not too familiar with operations that go beyond finding data in a single collection. Was googling approaches to achieve what I want to for days now, and thought it might be an idea to reach out to this community for a little help.

So here's my situation: I have 2 models, Artwork and UserInteraction:

const artworkSchema = new mongoose.Schema({
  slug:        {type: String, unique: true},
  title:       {type: String},
  content:     {type: String},
})
const Artwork = mongoose.model("Artwork", artworkSchema)

const userInteractionSchema = new mongoose.Schema({
  uid:         {type: String}, // Firebase User ID
  action:      {type: String, enum: ["LIKED",   "FOLLOWED"]},
  targetType:  {type: String, enum: ["ARTWORK", "GALLERY"]},
  targetKey:   {type: String, enum: ["SLUG",    "CODE"]},
  targetValue: {type: String}, // slug of liked/followed artwork, code of liked/followed gallery
  created:     {type: Date, default: () => new Date()},
})
const UserInteraction = mongoose.model("UserInteraction", userInteractionSchema)

The logic is that whenever a user does the action of "liking an artwork", a new UserInteraction is created:

const newUserInteraction = {
  uid:         "MyFirebaseUserId", // This user ..
  action:      "LIKED",            // .. liked ..
  targetType:  "ARTWORK",          // .. an artwork ..
  targetKey:   "SLUG",             // .. based on the artwork's slug, ..
  targetValue: "Artwork1Slug"      // .. which is 'ArtworkSlug1'
  // created will be set to now automatically (see UserInteraction schema)
}
// .. insert into DB

I would like to find a performant query that returns different results for different Firebase User IDs, it should basically

  1. find all artworks in database (could be in the 100.000s),
  2. find all user interactions with the criteria
{
  uid:        "MyFirebaseUserId",
  action:     "LIKED" ,
  targetType: "ARTWORK",
  targetKey:  "SLUG"
}
// in the example, this would return just one single entry, but in a real life scenario this could return hundreds of results:
[
  {
    uid:         "MyFirebaseUserId",
    action:      "LIKED",
    targetKey:   "ARTWORK",
    targetKey:   "SLUG",
    targetValue: "Artwork1Slug", // slug of the liked artwork
    created:     Fri Apr 29 2022 10:50:45 GMT+0200 (Central European Summer Time)
  }
]
  1. add the created value (if it exists for a given artwork) to the artworks returned in the first step,
  2. sort the resulting "enriched" artworks by this created value (highest values first, a.k.a. "last liked artworks" first, non-liked artworks last)
  3. respect a skip and limit value for the final output. I think it's important to do this in the query directly to improve performance.

I would be very thankful for anything that points me into the right direction with this!

EDIT: I've added this Mongo Playground snippet to illustrate my troubles.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source