So verbinden Sie mehrere Sammlungen mit $ lookup in mongodb


76

Ich möchte mit dem Aggregat mehr als zwei Sammlungen in MongoDB verbinden $lookup. Ist es möglich mitzumachen? Gib mir einige Beispiele.

Hier habe ich drei Sammlungen:

users::

{    
    "_id" : ObjectId("5684f3c454b1fd6926c324fd"),
    "email" : "admin@gmail.com",
    "userId" : "AD",
    "userName" : "admin"
}

userinfo::

{
    "_id" : ObjectId("56d82612b63f1c31cf906003"),
    "userId" : "AD",
    "phone" : "0000000000"
}

userrole::

{
    "_id" : ObjectId("56d82612b63f1c31cf906003"),
    "userId" : "AD",
    "role" : "admin"
}

Mögliches Duplikat von Bedingungen
styvane

Antworten:


115

Die Join-Funktion, die von Mongodb 3.2 und höheren Versionen unterstützt wird. Sie können Joins verwenden, indem Sie eine aggregierte Abfrage verwenden.
Sie können dies anhand des folgenden Beispiels tun:

db.users.aggregate([

    // Join with user_info table
    {
        $lookup:{
            from: "userinfo",       // other table name
            localField: "userId",   // name of users table field
            foreignField: "userId", // name of userinfo table field
            as: "user_info"         // alias for userinfo table
        }
    },
    {   $unwind:"$user_info" },     // $unwind used for getting data in object or for one record only

    // Join with user_role table
    {
        $lookup:{
            from: "userrole", 
            localField: "userId", 
            foreignField: "userId",
            as: "user_role"
        }
    },
    {   $unwind:"$user_role" },

    // define some conditions here 
    {
        $match:{
            $and:[{"userName" : "admin"}]
        }
    },

    // define which fields are you want to fetch
    {   
        $project:{
            _id : 1,
            email : 1,
            userName : 1,
            userPhone : "$user_info.phone",
            role : "$user_role.role",
        } 
    }
]);

Dies ergibt ein Ergebnis wie folgt:

{
    "_id" : ObjectId("5684f3c454b1fd6926c324fd"),
    "email" : "admin@gmail.com",
    "userName" : "admin",
    "userPhone" : "0000000000",
    "role" : "admin"
}

Hoffe das wird dir oder jemand anderem helfen.

Vielen Dank


Wenn Sie Daten in einem Array aus einer anderen Tabelle als nur $ unwind aus dieser Tabelle entfernen möchten , bedeutet dies, dass Sie " {$ unwind:" $ user_role "} " aus der Abfrage zum Abrufen von Daten in einem Array aus der Tabelle user_role entfernen
Amit Kumar

das war sehr hilfreich für mich; insbesondere die Verwendung von $ unwind und
Unterobjektreferenzen

Hallo, Amit, es sieht gut aus, aber es hat mein Problem nicht gelöst. Hier ist der Link. Bitte geben Sie eine Antwort: stackoverflow.com/questions/61188497/…
a zEnItH

Versuchen Sie $ unwind in Ihrer Abfrage für beide Join-Tabellen. @azEnItH
Amit Kumar

38

Sie können tatsächlich mehrere $ Lookup-Stufen verketten. Basierend auf den Namen der von profesor79 freigegebenen Sammlungen können Sie Folgendes tun:

db.sivaUserInfo.aggregate([
    {
        $lookup: {
           from: "sivaUserRole",
           localField: "userId",
           foreignField: "userId",
           as: "userRole"
        }
    },
    {
        $unwind: "$userRole"
    },
    {
        $lookup: {
            from: "sivaUserInfo",
            localField: "userId",
            foreignField: "userId",
            as: "userInfo"
        }
    },
    {
        $unwind: "$userInfo"
    }
])

Dies gibt die folgende Struktur zurück:

{
    "_id" : ObjectId("56d82612b63f1c31cf906003"),
    "userId" : "AD",
    "phone" : "0000000000",
    "userRole" : {
        "_id" : ObjectId("56d82612b63f1c31cf906003"),
        "userId" : "AD",
        "role" : "admin"
    },
    "userInfo" : {
        "_id" : ObjectId("56d82612b63f1c31cf906003"),
        "userId" : "AD",
        "phone" : "0000000000"
    }
}

Vielleicht könnte dies als Anti-Muster angesehen werden, da MongoDB nicht als relational gedacht war, aber es ist nützlich.


1
Was ist, wenn wir userinfo als Arry in der Benutzerrolle anzeigen möchten? wie das geht
Muneem Habib

14

Gemäß der Dokumentation kann $ lookup nur einer externen Sammlung beitreten.

Was Sie tun können, ist zu kombinieren userInfound userRolein einer Sammlung, wie angegeben, basiert das Beispiel auf einem relationalen DB-Schema. Mongo ist eine noSQL-Datenbank - und dies erfordert einen anderen Ansatz für die Dokumentenverwaltung.

Im Folgenden finden Sie eine zweistufige Abfrage, die userInfo mit userRole kombiniert und eine neue temporäre Sammlung erstellt, die in der letzten Abfrage zum Anzeigen kombinierter Daten verwendet wird. In der letzten Abfrage besteht die Möglichkeit, $ out zu verwenden und eine neue Sammlung mit zusammengeführten Daten für die spätere Verwendung zu erstellen.

Sammlungen erstellen

db.sivaUser.insert(
{    
    "_id" : ObjectId("5684f3c454b1fd6926c324fd"),
        "email" : "admin@gmail.com",
        "userId" : "AD",
        "userName" : "admin"
})

//"userinfo"
db.sivaUserInfo.insert(
{
    "_id" : ObjectId("56d82612b63f1c31cf906003"),
    "userId" : "AD",
    "phone" : "0000000000"
})

//"userrole"
db.sivaUserRole.insert(
{
    "_id" : ObjectId("56d82612b63f1c31cf906003"),
    "userId" : "AD",
    "role" : "admin"
})

"mach mit" allen :-)

db.sivaUserInfo.aggregate([
    {$lookup:
        {
           from: "sivaUserRole",
           localField: "userId",
           foreignField: "userId",
           as: "userRole"
        }
    },
    {
        $unwind:"$userRole"
    },
    {
        $project:{
            "_id":1,
            "userId" : 1,
            "phone" : 1,
            "role" :"$userRole.role"
        }
    },
    {
        $out:"sivaUserTmp"
    }
])


db.sivaUserTmp.aggregate([
    {$lookup:
        {
           from: "sivaUser",
           localField: "userId",
           foreignField: "userId",
           as: "user"
        }
    },
    {
        $unwind:"$user"
    },
    {
        $project:{
            "_id":1,
            "userId" : 1,
            "phone" : 1,
            "role" :1,
            "email" : "$user.email",
            "userName" : "$user.userName"
        }
    }
])

Hallo, Professor, Ihr Code sieht gut aus, hat aber mein Problem nicht gelöst. Ich gebe
a zEnItH

Weiß jemand, ob diese Aussage noch wahr ist : $lookup can join only one external collection? Ich habe keine Einschränkung im Dokumentlink gefunden. Danke
Israel Peck

0

Ich verstehe nicht, warum Sie eine Beziehung zur Benutzer-ID haben, warum Sie die Objekt-ID nicht verwenden, um beide Dokumente zu verknüpfen. Grüße.


0

Fügen Sie zuerst die Sammlungen hinzu und wenden Sie dann eine Suche auf diese Sammlungen an. Nicht $unwind zum Abwickeln verwenden, werden einfach alle Dokumente der einzelnen Sammlungen getrennt. Wenden Sie also eine einfache Suche an und verwenden Sie sie dann $projectfür die Projektion. Hier ist mongoDB Abfrage:

db.userInfo.aggregate([
    {
        $lookup: {
           from: "userRole",
           localField: "userId",
           foreignField: "userId",
           as: "userRole"
        }
    },
    {
        $lookup: {
            from: "userInfo",
            localField: "userId",
            foreignField: "userId",
            as: "userInfo"
        }
    },
    {$project: {
        "_id":0,
        "userRole._id":0,
        "userInfo._id":0
        }
        } ])

Hier ist die Ausgabe:

/* 1 */ {
    "userId" : "AD",
    "phone" : "0000000000",
    "userRole" : [ 
        {
            "userId" : "AD",
            "role" : "admin"
        }
    ],
    "userInfo" : [ 
        {
            "userId" : "AD",
            "phone" : "0000000000"
        }
    ] }

Vielen Dank.


1
Wenn eine Sammlung mehrere Dokumente enthält, werden alle Dokumente im Array angezeigt.
nixxo_raa
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.