2016-03-05 13 views
23

Chcę dołączyć do więcej niż dwóch kolekcji przy użyciu zagregowanego wyszukiwania $. czy można dołączyć? proszę dać mi znać, jeśli to możliwe. Daj mi przykład. Tutaj mam trzy kolekcje:

"użytkowników"

{  
"_id" : ObjectId("5684f3c454b1fd6926c324fd"), 
    "email" : "[email protected]", 
    "userId" : "AD", 
    "userName" : "admin" 
} 

"userinfo"

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

"userrole"

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

Możliwy duplikat [Multiple dołączyć warunki za pomocą operatora $ odnośnika] (https://stackoverflow.com/questions/37086387/multiple-join-conditions-using-the-lookup-operator) – styvane

+0

Possible duplikat [Jak mogę zapytać o obiekty odniesienia w MongoDB?] (https: // stackoverflow.com/questions/9621928/how-do-i-query-referenced-objects-in-mongodb) – sidgate

Odpowiedz

9

Według documentation, $ odnośnika może dołączyć tylko jedna kolekcja zewnętrzna.

Co można zrobić, to połączyć userInfo i userRole w jednej kolekcji, ponieważ podany przykład jest oparty na relacyjnym schemacie DB. Mongo to baza danych noSQL - wymaga to innego podejścia do zarządzania dokumentami.

Poniżej znajduje się zapytanie 2-etapowe, które łączy userInfo z userRole - tworząc nową kolekcję tymczasową używaną w ostatnim zapytaniu do wyświetlania połączonych danych. W ostatnim zapytaniu istnieje opcja użycia opcji $ out i utworzenia nowej kolekcji z scalonymi danymi do późniejszego wykorzystania.

tworzyć kolekcje

db.sivaUser.insert(
{  
    "_id" : ObjectId("5684f3c454b1fd6926c324fd"), 
     "email" : "[email protected]", 
     "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" 
}) 

"join" im wszystko :-)

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" 
     } 
    } 
]) 
+0

hmmm ........... –

+0

interesujący ... test wydajności? –

22

Można rzeczywiście łańcucha $ wielu etapów odnośników. Na podstawie nazw zbiorów udostępnionych przez profesor79, można to zrobić:

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" 
    } 
]) 

ten powróci następującą strukturę:

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

Może to może być uważany za anty-wzorzec ponieważ MongoDB wasn” ma być relacyjny, ale jest użyteczny.

+2

to rzeczywiście działa. Dzięki! –

+0

co jeśli chcemy wyświetlać userinfo jako arry w roli użytkownika? jak to zrobić –

16

Funkcja łączenia obsługiwana przez Mongodb 3.2 i nowsze wersje. Możesz użyć złączeń, używając zapytania agregującego.
Można to zrobić za pomocą poniższego przykładu:

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", 
     } 
    } 
]); 

To daje wynik tak:

{ 
    "_id" : ObjectId("5684f3c454b1fd6926c324fd"), 
    "email" : "[email protected]", 
    "userName" : "admin", 
    "userPhone" : "0000000000", 
    "role" : "admin" 
} 

nadzieję, że to pomoże ci lub kogoś innego.

Dzięki

+0

jeśli chcesz danych w tablicy z innej tabeli niż po prostu usunąć ** $ unwind ** z tej tabeli oznacza usunąć "** {$ unwind:" $ user_role "} **" z zapytania do pobierania danych w tablica z tabeli ** user_role ** –

Powiązane problemy