sql >> Databasteknik >  >> NoSQL >> MongoDB

Hitta ett dokument baserat på en hänvisning till föräldern i barnet

Det "bästa" sättet att göra detta är faktiskt snarare att använda .aggregate() och $lookup att "ansluta" till data och "filtrera" på matchvillkoren. Detta är mycket effektivt eftersom MongoDB faktiskt utför allt detta på "servern" själv, jämfört med att utfärda "flera" frågor som .populate() gör.

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

Om det finns "många" rankningar är det bäst att använda $unwind , som skapar ett dokument för varje relaterad "ranking"-post:

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

Det finns också en speciell hantering här av hur MongoDB hanterar att "ansluta" dokument för att undvika att bryta 16MB BSON-gränsen. Så i själva verket händer denna speciella sak när $unwind följer direkt en $lookup pipeline stage:

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

$unwind faktiskt "försvinner" och istället "rullas upp" i $lookup som om detta vore "en" operation. På så sätt skapar vi inte en "array" direkt i det överordnade dokumentet som skulle göra att storleken överstiger 16 MB i extrema fall med många "relaterade" objekt.

Om du inte har en MongoDB som stöder $lookup ( MongoDB 3.2 minunum ) då kan du använda en "virtuell" med .populate() istället (kräver minst Mongoose 4.5.0 ). Men observera att detta faktiskt utför "två" frågor till servern:

Lägg först till det "virtuella" i schemat:

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

Ge sedan frågan med .populate() :

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



  1. $unionWith – MongoDB:s motsvarighet till UNION ALL

  2. Redis butiksnyckel utan värde

  3. Hur man skjuter nya objekt till en array inuti ett objekt

  4. MongoDB-värdalternativ nu när Heroku mLab-tillägget tas bort