MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Finden Sie ein Dokument basierend auf einem Verweis auf das Elternteil im Kind

Eigentlich ist der "beste" Weg, dies zu tun, eher die Verwendung von .aggregate() und $lookup um die Daten zu "verknüpfen" und nach den Spielbedingungen zu "filtern". Dies ist sehr effektiv, da MongoDB all dies tatsächlich auf dem "Server" selbst durchführt, im Vergleich zur Ausgabe "mehrerer" Abfragen als .populate() tut.

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

Wenn es „viele“ Rankings gibt, verwenden Sie am besten $unwind , wodurch ein Dokument für jedes zugehörige "Ranking"-Element erstellt wird:

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

Hier gibt es auch eine spezielle Handhabung, wie MongoDB mit dem „Zusammenführen“ von Dokumenten umgeht, um ein Überschreiten der 16-MB-BSON-Grenze zu vermeiden. Tatsächlich passiert also diese besondere Sache, wenn $unwind folgt direkt auf $lookup Pipeline-Phase:

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

Also der $unwind tatsächlich "verschwindet" und stattdessen in den <-Code "aufgerollt" wird>$nachschlagen als wäre dies "eine" Operation. Auf diese Weise erstellen wir kein "Array" direkt im übergeordneten Dokument, das bei vielen "verwandten" Elementen im Extremfall die Größe von 16 MB überschreiten würde.

Wenn Sie keine MongoDB haben, die $lookup (MongoDB mindestens 3.2 ), dann könnten Sie ein "virtuelles" mit .populate() verwenden stattdessen (erfordert mindestens Mongoose 4.5.0 ). Beachten Sie jedoch, dass dies tatsächlich "zwei" ausführt Anfragen an den Server:

Fügen Sie zuerst das "virtuelle" zum Schema hinzu:

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

Setzen Sie dann die Abfrage mit .populate() ab :

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