Puoi fare un raw
interrogare con aggregate()
che può utilizzare $lookup
operatore per effettuare il "join" qui:
$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 )
));
});
Il $lookup
restituirà un "array" per il campo target contenente "none" o più voci corrispondenti al 'localField'
fornito value(s), dove è singolare o una matrice di valori. In genere utilizziamo ObjectId
qui, specialmente quando ci si collega a 'foreignField'
come _id
.
Questo è meglio di qualsiasi altra cosa che può essere eseguita lato client, poiché qualsiasi altra operazione richiederebbe l'esecuzione di più query al database per ciascuna origine della raccolta. $lookup
lo fa in un'unica richiesta e risposta.
L'unica vera nota è che poiché questo è "separato" dall'ORM/ODM, è necessario specificare il "nome della raccolta" effettivo e non quello della classe o del modello. Quindi sto solo presumendo "users"
qui, ma forse dovrai adattarlo alla tua raccolta per Users
viene effettivamente chiamato.
Ad ogni modo, dopo aver ottenuto i dati "uniti", puoi $match
nel "usrEmail"
proprietà dai dati uniti e includi nella tua query.
Per quanto riguarda la query vera e propria, dato che in pratica stai eseguendo un $or
condizione tra i dati di entrambe le raccolte non possiamo davvero $match
fino a quando "dopo" l'unione viene eseguita.
Poi ovviamente ci sono le fasi di aggregazione per $skip
e $limit
anche per la tua impaginazione.