Puedes hacer un raw
consulta con aggregate()
que puede usar el $lookup
operador para efectuar la "unión" aquí:
$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 )
));
});
El $lookup
devolverá una "matriz" para el campo de destino que contiene "ninguna" o más entradas coincidentes con el 'localField'
proporcionado value(s), donde es singular o una matriz de valores. Normalmente usamos ObjectId
aquí, especialmente cuando se vincula a 'foreignField'
como _id
.
Esto es mejor que cualquier cosa que se pueda hacer del lado del cliente, ya que cualquier otra operación requeriría realizar múltiples consultas a la base de datos para cada fuente de recopilación. $lookup
hace esto en una sola solicitud y respuesta.
La única nota real es que debido a que esto es "separado" del ORM/ODM, debe especificar el "nombre de la colección" real y no el de la clase o el modelo. Así que solo estoy suponiendo "users"
aquí, pero tal vez necesite ajustar eso a su colección para Users
se llama realmente.
De todos modos, después de tener los datos "unidos", puede $match
en el "usrEmail"
propiedad de los datos unidos, e incluir en su consulta.
En cuanto a la consulta real, dado que básicamente está haciendo un $or
condición a través de los datos de ambas colecciones realmente no podemos $match
hasta "después" de que se realice la unión.
Luego, por supuesto, están las etapas de agregación para $skip
y $limit
para su paginación también.