Skip to content Skip to sidebar Skip to footer

Find A Document Based On A Reference To The Parent In The Child

There are 2 collections Movie and Rank Movie .This 2 collections having referenced relationship . Movie model var mongoose = require('mongoose'); var movieSchema = new mongoose.S

Solution 1:

Actually the "best" way to do this is rather using .aggregate() and $lookup to "join" the data and "filter" on the match conditions. This is very effective since MongoDB actually performs all of this on the "server" itself, as compared to issuing "multiple" queries as .populate() does.

MovieModel.aggregate([
  { "$match": { "m_title": m_title } },
  { "$lookup": {
    "from": RankMovieModel.collection.name,
    "localField": "_id",
    "foreignField": "movie",
    "as": "rankings"
  }}
])

Note: The RankMovieModel.collection.name is a nice way of getting the "underlying" collection name from the Model registered with Mongoose. Since the operation is on the "server", MongoDB needs the "real collection name", so we can either "hardcode" that or just get it from the information registered on the Model itself. As is done here.

If there are "lots" of rankings, then you are best to use $unwind, which will create a document for each related "rankings" item:

MovieModel.aggregate([
  { "$match": { "m_title": m_title } },
  { "$lookup": {
    "from": RankMovieModel.collection.name,
    "localField": "_id",
    "foreignField": "movie",
    "as": "rankings"
  }},
  { "$unwind": "$rankings" }
])

There is also a special handling here of how MongoDB deals with "joining" documents to avoid breaching the 16MB BSON limit. So in fact this special thing happens when $unwind directly follows a $lookup pipeline stage:

    {
        "$lookup" : {
            "from" : "rankmovies",
            "as" : "rankings",
            "localField" : "_id",
            "foreignField" : "movie",
            "unwinding" : {
                "preserveNullAndEmptyArrays" : false
            }
        }
    }

So the $unwind actually "disappears" and instead is "rolled-up" into the $lookup itself as if this were "one" operation. That way we do not create an "array" directly within the parent document which would cause the size to exceed 16MB in extreme cases with many "related" items.


If you do not have a MongoDB that supports $lookup ( MongoDB 3.2 minunum ) then you could use a "virtual" with .populate() instead (requires Mongoose 4.5.0 minimum). But note this actually performs "two" queries to the server:

First add the "virtual" to the schema:

movieSchema.virtual("rankings",{
  "ref": "Movie",
  "localField": "_id",
  "foreignField": "movie"
});

Then issue the query with .populate():

MovieModel.find({ "m_title": m_title })
  .populate('rankings')
  .exec()

Post a Comment for "Find A Document Based On A Reference To The Parent In The Child"