641 Stimmen

Wie führe ich den SQL-Join in MongoDB aus?

Wie führe ich den SQL-Join in MongoDB aus?

Nehmen wir an, Sie haben zwei Sammlungen (Benutzer und Kommentare), und ich möchte alle Kommentare mit pid=444 zusammen mit den Benutzerinformationen für jeden abrufen.

comments
  { uid:12345, pid:444, comment="blah" }
  { uid:12345, pid:888, comment="asdf" }
  { uid:99999, pid:444, comment="qwer" }

users
  { uid:12345, name:"john" }
  { uid:99999, name:"mia"  }

Gibt es eine Möglichkeit, alle Kommentare mit einem bestimmten Feld (z. B. ...find({pid:444}) ) und die mit jedem Kommentar verknüpften Benutzerinformationen in einem Rutsch zu finden?

Im Moment erhalte ich zuerst die Kommentare, die meinen Kriterien entsprechen, dann finde ich alle uid's in diesem Ergebnissatz heraus, erhalte die Benutzerobjekte und führe sie mit den Ergebnissen des Kommentars zusammen. Es scheint, dass ich das falsch mache.

67 Stimmen

Die letzte Antwort auf diese Frage ist wahrscheinlich die wichtigste, da MongoDB 3.2+ eine Join-Lösung namens $lookup implementiert hat. Ich dachte, ich würde sie hier einfügen, weil vielleicht nicht jeder bis zum Ende liest. stackoverflow.com/a/33511166/2593330

10 Stimmen

Richtig, $Nachschlag wurde in MongoDB 3.2 eingeführt. Einzelheiten finden Sie unter docs.mongodb.org/master/reference/operator/aggregation/lookup/

0 Stimmen

Konvertieren Sie eine beliebige Abfrage in Mongo und prüfen Sie die Antwort: stackoverflow.com/questions/68155715/

0voto

Dean Hiller Punkte 17963

PlayORM kann dies für Sie tun, indem es S-SQL (Scalable SQL) verwendet, das lediglich eine Partitionierung hinzufügt, so dass Sie Joins innerhalb von Partitionen durchführen können.

-2voto

Michael Cole Punkte 14357

Nein, es sieht nicht so aus, als ob Sie es falsch machen. MongoDB-Joins sind "clientseitig". Ziemlich genau wie du gesagt hast:

Im Moment erhalte ich zunächst die Kommentare, die meine Kriterien erfüllen, dann herauszufinden, alle uid's in dieser Ergebnismenge, erhalten die Benutzer-Objekte, und verschmelzen sie mit den Ergebnissen des Kommentars. Es scheint, dass ich das falsch mache.

1) Select from the collection you're interested in.
2) From that collection pull out ID's you need
3) Select from other collections
4) Decorate your original results.

Es ist keine "echte" Verknüpfung, aber es ist eigentlich viel nützlicher als eine SQL-Verknüpfung, weil Sie nicht mit doppelten Zeilen für "viele" sided joins zu tun haben, stattdessen Ihre Dekoration der ursprünglich ausgewählten Satz.

Es gibt eine Menge Unsinn und FUD auf dieser Seite. Wie sich herausstellt, ist MongoDB 5 Jahre später immer noch eine Sache.

0 Stimmen

Sie müssen sich nicht mit doppelten Zeilen für "vielseitige" Verknüpfungen befassen. - keine Ahnung, was Sie damit meinen. Können Sie das klären?

2 Stimmen

@MarkAmery, sicher. In SQL wird eine n-n-Beziehung doppelte Zeilen liefern. Z.B. Freunde. Wenn Bob mit Mary und Jane befreundet ist, erhältst du 2 Zeilen für Bob: Bob,Mary und Bob,Jane. 2 Bobs sind eine Lüge, es gibt nur einen Bob. Mit clientseitigen Joins können Sie mit Bob beginnen und ihn nach Belieben dekorieren: Bob, "Mary und Jane". Mit SQL kann man das mit Unterabfragen machen, aber das bedeutet Arbeit auf dem Datenbankserver, die auf dem Client erledigt werden könnte.

-3voto

Max Sherbakov Punkte 1495

Ich denke, wenn Sie normalisierte Datentabellen benötigen, müssen Sie andere Datenbanklösungen ausprobieren.

Aber ich habe die Lösung für MOngo gefunden auf Git Übrigens, im Einfügecode steht der Name des Films, aber noi Film's ID .

Problem

Sie haben eine Sammlung von Schauspielern mit einer Reihe von Filmen, die sie gemacht haben.

Sie möchten eine Sammlung von Filmen mit einem Array von Schauspielern in jedem Film erstellen.

Einige Beispieldaten

 db.actors.insert( { actor: "Richard Gere", movies: ['Pretty Woman', 'Runaway Bride', 'Chicago'] });
 db.actors.insert( { actor: "Julia Roberts", movies: ['Pretty Woman', 'Runaway Bride', 'Erin Brockovich'] });

Lösung

Wir müssen eine Schleife durch jeden Film im Actor-Dokument ziehen und jeden Film einzeln ausgeben.

Der Haken an der Sache ist die Phase des Reduzierens. Wir können kein Array aus der Reduzierungsphase ausgeben, also müssen wir ein Actors-Array innerhalb des zurückgegebenen "Wert"-Dokuments erstellen.

Der Code

map = function() {
  for(var i in this.movies){
    key = { movie: this.movies[i] };
    value = { actors: [ this.actor ] };
    emit(key, value);
  }
}

reduce = function(key, values) {
  actor_list = { actors: [] };
  for(var i in values) {
    actor_list.actors = values[i].actors.concat(actor_list.actors);
  }
  return actor_list;
}

Beachten Sie, wie actor_list ist eigentlich ein Javascript-Objekt, das ein Array enthält. Beachten Sie auch, dass map die gleiche Struktur ausgibt.

Führen Sie Folgendes aus, um die Map/Reduction auszuführen, sie in der Pivot-Sammlung auszugeben und das Ergebnis zu drucken:

printjson(db.actors.mapReduce(map, reduce, "pivot")); db.pivot.find().forEach(printjson);

Beachten Sie, dass "Pretty Woman" und "Runaway Bride" sowohl "Richard Gere" als auch "Julia Roberts" enthalten.

{ "_id" : { "movie" : "Chicago" }, "value" : { "actors" : [ "Richard Gere" ] } }
{ "_id" : { "movie" : "Erin Brockovich" }, "value" : { "actors" : [ "Julia Roberts" ] } }
{ "_id" : { "movie" : "Pretty Woman" }, "value" : { "actors" : [ "Richard Gere", "Julia Roberts" ] } }
{ "_id" : { "movie" : "Runaway Bride" }, "value" : { "actors" : [ "Richard Gere", "Julia Roberts" ] } }

0 Stimmen

Beachten Sie, dass der größte Teil des Inhalts dieser Antwort (d. h. der Teil, der in verständlichem Englisch ist) aus dem MongoDB-Kochbuch unter dem GitHub-Link kopiert wurde, den der Antwortende angegeben hat.

-6voto

Krishna Punkte 1

Wir können zwei Sammlungen zusammenführen, indem wir eine MongoDB-Unterabfrage verwenden. Hier ein Beispiel, Kommentare--

`db.commentss.insert([
  { uid:12345, pid:444, comment:"blah" },
  { uid:12345, pid:888, comment:"asdf" },
  { uid:99999, pid:444, comment:"qwer" }])`

Benutzer--

db.userss.insert([
  { uid:12345, name:"john" },
  { uid:99999, name:"mia"  }])

MongoDB-Unterabfrage für JOIN--

`db.commentss.find().forEach(
    function (newComments) {
        newComments.userss = db.userss.find( { "uid": newComments.uid } ).toArray();
        db.newCommentUsers.insert(newComments);
    }
);`

Ergebnis der neu erstellten Sammlung abrufen.

db.newCommentUsers.find().pretty()

Ergebnis:

`{
    "_id" : ObjectId("5511236e29709afa03f226ef"),
    "uid" : 12345,
    "pid" : 444,
    "comment" : "blah",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f2"),
            "uid" : 12345,
            "name" : "john"
        }
    ]
}
{
    "_id" : ObjectId("5511236e29709afa03f226f0"),
    "uid" : 12345,
    "pid" : 888,
    "comment" : "asdf",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f2"),
            "uid" : 12345,
            "name" : "john"
        }
    ]
}
{
    "_id" : ObjectId("5511236e29709afa03f226f1"),
    "uid" : 99999,
    "pid" : 444,
    "comment" : "qwer",
    "userss" : [
        {
            "_id" : ObjectId("5511238129709afa03f226f3"),
            "uid" : 99999,
            "name" : "mia"
        }
    ]
}`

Ich hoffe, das wird helfen.

10 Stimmen

Warum haben Sie im Grunde diese fast identische, ein Jahr alte Antwort kopiert? stackoverflow.com/a/22739813/4186945

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X