如何使用Laravel和MongoDB匹配加入的集合?

如何使用Laravel和MongoDB匹配加入的集合?,mongodb,laravel,mongodb-query,aggregation-framework,Mongodb,Laravel,Mongodb Query,Aggregation Framework,我有两个系列“预订”和“用户”。在“预订”集合中,我有一个字段“用户”。它与“用户”\u id“相关 我有一个预订列表页面。在此列表页面中,显示来自“预订”和“用户”的数据 在这个列表页面中,我有一个文本框来搜索发票号、付款类型、txid和usrEmail。我已经写了查询来搜索发票号、付款类型、txid,它正在工作,但我被困在usrEmail部分。我如何与用户结合并编写搜索查询以搜索usrEmail 我正在使用laravel和mongodb。我在跟踪“ 预订 \u id、用户、发票号、付款类型、

我有两个系列“预订”和“用户”。在“预订”集合中,我有一个字段
“用户”
。它与
“用户”\u id“
相关

我有一个预订列表页面。在此列表页面中,显示来自“预订”和“用户”的数据

在这个列表页面中,我有一个文本框来搜索
发票号、付款类型、txid和usrEmail
。我已经写了查询来搜索
发票号、付款类型、txid
,它正在工作,但我被困在
usrEmail
部分。我如何与
用户
结合并编写搜索查询以搜索
usrEmail

我正在使用laravel和mongodb。我在跟踪“

预订

\u id、用户、发票号、付款类型、txid

用户

\u id,firstName,SecondName,usrEmail

搜索查询

$bookings = Booking::select('_id', 'invoice_number', 'temp_user_id', 'user', 'checkin_from', 'reserve_to', 'beds', 'dormitory', 'sleeps', 'status', 'payment_status', 'payment_type', 'total_prepayment_amount', 'cabinname', 'reference_no', 'clubmember', 'bookingdate', 'txid')
                ->where('is_delete', 0)
                ->where(function($query) use ($search) { /* That's the closure */
                    $query->where('invoice_number', 'like', "%{$search}%")
                        ->orWhere('payment_type', 'like', "%{$search}%")
                        ->orWhere('txid', 'like', "%{$search}%");
                })
                ->skip($start)
                ->take($limit)
                ->orderBy($order, $dir)
                ->get();
App\Booking

public function user()
    {
        return $this->hasOne('App\Userlist', 'user', '_id');
    }
两个系列的图像 用户 预订

用户集合

{ "_id" : ObjectId("57877d23049ac1b819000029"), "usrName" : "adminuser", "usrPassword" : "96a65063135247fef732b5901fe05d1f", "usrFirstname" : "Sarath", "usrLastname" : "TS", "usrTelephone" : null, "usrEmail" : "sara@gmail.com", "usrMobile" : "956209959", "usrAddress" : null, "usrFax" : "4564654", "usrZip" : null, "usrBirthday" : null, "usrDAV" : "316148-DAV-Deutscher Alpenverein", "usrActive" : "1", "usrlId" : "1", "lngId" : "1", "usrPasswordSalt" : ";:?hJM\"9=z/)ea?{%-[**:]68UOT>{gj^{P0+RCF#,Id8c:n+h", "usrRegistrationDate" : ISODate("2016-07-14T11:53:07Z"), "usrRegistrationToken" : "2c2e296bda1661c7fc0645f927d0b17f", "is_delete" : "0", "usrUpdateDate" : ISODate("2017-05-16T09:12:07Z"), "usrPasswordDate" : ISODate("2016-10-25T07:35:57Z"), "usrCity" : null, "usrNewsletter" : null, "money_balance" : "0", "usrCountry" : "Deutschland" }
{ "_id" : ObjectId("58046a49f8f888a80b00002a"), "cabinname" : "Matras-Haus", "checkin_from" : ISODate("2016-10-17T00:00:00Z"), "reserve_to" : ISODate("2016-10-20T00:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "2", "dormitory" : "1", "sleeps" : "3", "clubmember" : "1", "status" : "4", "comments" : "", "bookingdate" : ISODate("2016-10-17T06:06:01Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1), "payment_status" : "1" }
{ "_id" : ObjectId("58183678d2ae67a404431d5c"), "cabinname" : "Kemptner Hütte", "checkin_from" : ISODate("2016-10-31T23:00:00Z"), "reserve_to" : ISODate("2016-11-23T23:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "2", "dormitory" : "0", "sleeps" : "2", "clubmember" : "0", "status" : "1", "total_price" : "1288", "payon_cabin" : "1288", "bed_prefer" : "0", "guests" : "2", "comments" : "", "prepayment_amount" : "0", "bookingdate" : ISODate("2016-11-01T06:30:16Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1), "payment_status" : "0" }
{ "_id" : ObjectId("581b31f3d2ae674d5f431d5b"), "cabinname" : "Kemptner Hütte", "checkin_from" : ISODate("2016-11-07T23:00:00Z"), "reserve_to" : ISODate("2016-11-17T23:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "3", "dormitory" : "0", "sleeps" : "3", "clubmember" : "0", "status" : "1", "total_price" : "840", "payon_cabin" : "840", "bed_prefer" : "0", "guests" : "3", "comments" : "", "prepayment_amount" : "0", "bookingdate" : ISODate("2016-11-03T12:47:47Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1) }
{ "_id" : ObjectId("5821af65d2ae67c82154efc5"), "cabinname" : "Kemptner Hütte", "checkin_from" : ISODate("2017-09-05T22:00:00Z"), "reserve_to" : ISODate("2018-01-24T23:00:00Z"), "user" : "57877d23049ac1b819000029", "sleeps" : "2", "clubmember" : "0", "status" : "1", "total_price" : "5640", "payon_cabin" : "5630", "bed_prefer" : "0", "guests" : "2", "comments" : "", "prepayment_amount" : "21.25", "bookingdate" : ISODate("2016-11-08T10:56:37Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1) }
{ "_id" : ObjectId("582558d4d2ae679c4d8b4567"), "cabinname" : "2", "checkin_from" : ISODate("2017-07-31T22:00:00Z"), "reserve_to" : ISODate("2017-08-02T22:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "", "dormitory" : "", "sleeps" : "2", "clubmember" : "0", "status" : "", "total_price" : "80", "payon_cabin" : "60", "halfboard" : "", "bed_prefer" : "0", "guests" : "2", "prepayment_amount" : "20", "bookingdate" : ISODate("2016-11-11T05:36:20Z"), "is_delete" : NumberLong(1) }
{ "_id" : ObjectId("58352c3cd2ae672341ec89e1"), "cabinname" : "Kemptner Hütte", "checkin_from" : ISODate("2017-05-31T22:00:00Z"), "reserve_to" : ISODate("2017-06-02T22:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "", "dormitory" : "", "sleeps" : "2", "clubmember" : "0", "status" : "", "total_price" : "80", "payon_cabin" : "60", "halfboard" : "", "bed_prefer" : "0", "guests" : "2", "prepayment_amount" : "20", "bookingdate" : ISODate("2016-11-23T05:42:20Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1) }
预订集合

{ "_id" : ObjectId("57877d23049ac1b819000029"), "usrName" : "adminuser", "usrPassword" : "96a65063135247fef732b5901fe05d1f", "usrFirstname" : "Sarath", "usrLastname" : "TS", "usrTelephone" : null, "usrEmail" : "sara@gmail.com", "usrMobile" : "956209959", "usrAddress" : null, "usrFax" : "4564654", "usrZip" : null, "usrBirthday" : null, "usrDAV" : "316148-DAV-Deutscher Alpenverein", "usrActive" : "1", "usrlId" : "1", "lngId" : "1", "usrPasswordSalt" : ";:?hJM\"9=z/)ea?{%-[**:]68UOT>{gj^{P0+RCF#,Id8c:n+h", "usrRegistrationDate" : ISODate("2016-07-14T11:53:07Z"), "usrRegistrationToken" : "2c2e296bda1661c7fc0645f927d0b17f", "is_delete" : "0", "usrUpdateDate" : ISODate("2017-05-16T09:12:07Z"), "usrPasswordDate" : ISODate("2016-10-25T07:35:57Z"), "usrCity" : null, "usrNewsletter" : null, "money_balance" : "0", "usrCountry" : "Deutschland" }
{ "_id" : ObjectId("58046a49f8f888a80b00002a"), "cabinname" : "Matras-Haus", "checkin_from" : ISODate("2016-10-17T00:00:00Z"), "reserve_to" : ISODate("2016-10-20T00:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "2", "dormitory" : "1", "sleeps" : "3", "clubmember" : "1", "status" : "4", "comments" : "", "bookingdate" : ISODate("2016-10-17T06:06:01Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1), "payment_status" : "1" }
{ "_id" : ObjectId("58183678d2ae67a404431d5c"), "cabinname" : "Kemptner Hütte", "checkin_from" : ISODate("2016-10-31T23:00:00Z"), "reserve_to" : ISODate("2016-11-23T23:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "2", "dormitory" : "0", "sleeps" : "2", "clubmember" : "0", "status" : "1", "total_price" : "1288", "payon_cabin" : "1288", "bed_prefer" : "0", "guests" : "2", "comments" : "", "prepayment_amount" : "0", "bookingdate" : ISODate("2016-11-01T06:30:16Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1), "payment_status" : "0" }
{ "_id" : ObjectId("581b31f3d2ae674d5f431d5b"), "cabinname" : "Kemptner Hütte", "checkin_from" : ISODate("2016-11-07T23:00:00Z"), "reserve_to" : ISODate("2016-11-17T23:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "3", "dormitory" : "0", "sleeps" : "3", "clubmember" : "0", "status" : "1", "total_price" : "840", "payon_cabin" : "840", "bed_prefer" : "0", "guests" : "3", "comments" : "", "prepayment_amount" : "0", "bookingdate" : ISODate("2016-11-03T12:47:47Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1) }
{ "_id" : ObjectId("5821af65d2ae67c82154efc5"), "cabinname" : "Kemptner Hütte", "checkin_from" : ISODate("2017-09-05T22:00:00Z"), "reserve_to" : ISODate("2018-01-24T23:00:00Z"), "user" : "57877d23049ac1b819000029", "sleeps" : "2", "clubmember" : "0", "status" : "1", "total_price" : "5640", "payon_cabin" : "5630", "bed_prefer" : "0", "guests" : "2", "comments" : "", "prepayment_amount" : "21.25", "bookingdate" : ISODate("2016-11-08T10:56:37Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1) }
{ "_id" : ObjectId("582558d4d2ae679c4d8b4567"), "cabinname" : "2", "checkin_from" : ISODate("2017-07-31T22:00:00Z"), "reserve_to" : ISODate("2017-08-02T22:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "", "dormitory" : "", "sleeps" : "2", "clubmember" : "0", "status" : "", "total_price" : "80", "payon_cabin" : "60", "halfboard" : "", "bed_prefer" : "0", "guests" : "2", "prepayment_amount" : "20", "bookingdate" : ISODate("2016-11-11T05:36:20Z"), "is_delete" : NumberLong(1) }
{ "_id" : ObjectId("58352c3cd2ae672341ec89e1"), "cabinname" : "Kemptner Hütte", "checkin_from" : ISODate("2017-05-31T22:00:00Z"), "reserve_to" : ISODate("2017-06-02T22:00:00Z"), "user" : "57877d23049ac1b819000029", "beds" : "", "dormitory" : "", "sleeps" : "2", "clubmember" : "0", "status" : "", "total_price" : "80", "payon_cabin" : "60", "halfboard" : "", "bed_prefer" : "0", "guests" : "2", "prepayment_amount" : "20", "bookingdate" : ISODate("2016-11-23T05:42:20Z"), "reservation_cancel" : "2", "is_delete" : NumberLong(1) }

您可以使用
aggregate()
执行
raw
查询,该查询可以使用运算符在此处实现“连接”:

将为包含“无”或多个匹配项的目标字段返回一个“数组”到提供的
'localField'
值,其中该值为单数或一个值数组。通常我们在这里使用
ObjectId
,尤其是当链接到
'foreignField'
作为
\u id

这比客户端可以完成的任何操作都要好,因为任何其他操作都需要对每个集合源的数据库进行多个查询。在单个请求和响应中执行此操作

唯一值得注意的是,因为它与ORM/ODM“分离”,所以需要指定实际的“集合名称”,而不是类或模型的名称。因此,我在这里假定
为“用户”
,但您可能需要根据
用户的集合实际调用的内容进行调整

无论如何,在获得“联接”数据后,您可以从联接的数据中在
“usrEmail”
属性上执行操作,并将其包括在查询中

至于实际的查询,由于您基本上是对来自两个集合的数据执行
$或
条件,因此在执行“after”联接之前,我们无法真正执行查询


当然还有分页的聚合阶段。

您可以使用
aggregate()
执行
raw
查询,该查询可以使用运算符在此处实现“连接”:

将为包含“无”或多个匹配项的目标字段返回一个“数组”到提供的
'localField'
值,其中该值为单数或一个值数组。通常我们在这里使用
ObjectId
,尤其是当链接到
'foreignField'
作为
\u id

这比客户端可以完成的任何操作都要好,因为任何其他操作都需要对每个集合源的数据库进行多个查询。在单个请求和响应中执行此操作

唯一值得注意的是,因为它与ORM/ODM“分离”,所以需要指定实际的“集合名称”,而不是类或模型的名称。因此,我在这里假定
为“用户”
,但您可能需要根据
用户的集合实际调用的内容进行调整

无论如何,在获得“联接”数据后,您可以从联接的数据中在
“usrEmail”
属性上执行操作,并将其包括在查询中

至于实际的查询,由于您基本上是对来自两个集合的数据执行
$或
条件,因此在执行“after”联接之前,我们无法真正执行查询


当然还有分页的聚合阶段。

非常感谢。我已经添加了这个,但是我面临一个问题“未知的顶级操作员:$user.usrEmail”。@samsam Typo。很抱歉更正。我确实有你的意图,对吗?您想要在所有这些可能的字段中进行“regex”或“类似SQL”的搜索吗?谢谢。目前,搜索不适用于usrEmail<代码>'localField'=>'user','foreignField'=>'\u id'
localField的意思是
预订。用户是否正确?@samsam是。我注意到这里的“join”假设依赖于相互关联的
“localField”
“foreignField”
,它们必须包含相同的数据类型。因此,如果这是一个1:1的关系,那么您需要在“bookings”中存储一些东西,使用
\u id
中的值。或者这就是我正在研究的假设。如果预订中的
用户
实际上引用了
\u id
以外的另一个“外来”字段,则将其指向该字段。所有内容都在
$lookup
文档中,该文档在答案中链接。@samsam显示您在问题中的操作。请包括从mongo shell查看的预订和用户的父文档和相关文档。请使用shell,因为它显示了分配的正确数据类型,而其他转储表单通常会忽略这些类型。那么我就可以清楚地看到你的想法和建议了。非常感谢你。我已经添加了这个,但是我面临一个问题“未知的顶级操作员:$user.usrEmail”。@samsam Typo。很抱歉更正。我确实有你的意图,对吗?您想要在所有这些可能的字段中进行“regex”或“类似SQL”的搜索吗?谢谢。目前,搜索不适用于usrEmail<代码>'localField'=>'user','foreignField'=>'\u id'
localField的意思是
预订。用户是否正确?@samsam是。我注意到这里的“join”假设依赖于相互关联的
“localField”
“foreignField”
,它们必须包含相同的数据类型。如果这是一个1:1的关系