Możesz zrobić surowy
zapytanie z aggregate()
które mogą korzystać z $lookup
operatora, aby wprowadzić tutaj „join”:
$result = Booking::raw(function($collection) use($search, $start, $limit) {
return $collection->aggregate(array(
array( '$lookup' => array(
'from' => 'users',
'localField' => 'user',
'foreignField' => '_id',
'as' => 'user'
)),
array( '$unwind' => array(
'path' => '$user', 'preserveNullAndEmptyArrays' => True
)),
array( '$match' => array(
'$or' => array(
array( 'invoice_number' => array( '$regex' => $search ) ),
array( 'payment_type' => array( '$regex' => $search ) ),
array( 'txid' => array( '$regex' => $search ) ),
array( 'user.usrEmail' => array( '$regex' => $search ) )
)
)),
array( '$skip' => $start ),
array( '$limit' => $limit )
));
});
$lookup
zwróci "tablicę" dla pola docelowego zawierającego "brak" lub więcej pasujących wpisów do dostarczonego 'localField'
wartości, gdzie jest to liczba pojedyncza lub tablica wartości. Zazwyczaj używamy ObjectId
tutaj, zwłaszcza gdy łączysz się z 'foreignField'
jako _id
.
Jest to lepsze niż cokolwiek, co można zrobić po stronie klienta, ponieważ każda inna operacja wymagałaby wykonania wielu zapytań do bazy danych dla każdego źródła kolekcji. $lookup
robi to w jednym żądaniu i odpowiedzi.
Jedyną prawdziwą uwagą jest to, że ponieważ jest to „oddzielne” od ORM/ODM, musisz określić rzeczywistą „nazwę kolekcji”, a nie nazwę klasy lub modelu. Więc zakładam, że "użytkownicy"
tutaj, ale być może będziesz musiał dostosować to do swojej kolekcji dla Users
jest faktycznie nazywany.
W każdym razie po „połączonych” danych możesz $match
na "usrEmail"
właściwości z połączonych danych i uwzględnij w zapytaniu.
Jeśli chodzi o rzeczywiste zapytanie, ponieważ zasadniczo robisz $lub
warunek w danych z obu kolekcji, tak naprawdę nie możemy $match
aż do wykonania połączenia „po”.
Oczywiście są też etapy agregacji dla $skip
i $limit
dla twojej paginacji.