Du kan lave en rå
forespørgsel med aggregate()
som kan bruge $lookup
operatør for at udføre "join" her:
$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
returnerer et "array" for målfeltet, der indeholder "ingen" eller flere matchende poster til det leverede 'localField'
værdi(er), hvor det enten er ental eller en række værdier. Typisk bruger vi ObjectId
her, især når du linker til 'foreignField'
som _id
.
Dette er bedre end noget, der kan udføres på klientsiden, da enhver anden operation ville kræve at lave flere forespørgsler til databasen for hver samlingskilde. $lookup
gør dette i en enkelt anmodning og svar.
Den eneste rigtige note er, at fordi dette er "adskilt" fra ORM/ODM, skal du angive det faktiske "samlingsnavn" og ikke klassens eller modellens navn. Så jeg går bare ud fra "brugere"
her, men du bliver måske nødt til at justere det til, hvad din samling for Brugere
hedder faktisk.
Under alle omstændigheder, når du har de "tilsluttede" data, kan du $match
på "usrEmail"
egenskab fra de sammenføjede data, og medtag i din forespørgsel.
Med hensyn til selve forespørgslen, da du dybest set laver en $or
tilstand på tværs af data fra begge samlinger, kan vi ikke rigtig $match
indtil "efter" sammenføjningen er udført.
Så er der selvfølgelig aggregeringsstadierne for $skip
og $limit
også for din paginering.