$lookup 嵌套对象数组
Posted
技术标签:
【中文标题】$lookup 嵌套对象数组【英文标题】:$lookup with nested array of objects 【发布时间】:2018-11-30 15:16:27 【问题描述】:我的文档有多个对象的数组,我需要找到相关的值并推入同一个数组。
购物车
"_id" : ObjectId("5b2b72119fbb60750e0061b9"),
"cartId" : "1529573905701",
"supplierId" : ObjectId("5b221d1b63eda2902418434d"),
"user_id" : "5b20c54651e68057b3cbe745",
"createdAt" : ISODate("2018-06-21T09:38:25.680Z"),
"services" : [
"date" : "21-06-2018",
"timeSlot_id" : ObjectId("5b29e08cb116c31f5b1f56c6"),
"time" : "03:30 PM - 04:30 PM",
"serviceId" : ObjectId("5b24aff4abf2494701bc1c15"),
"cost" : 250,
"_id" : ObjectId("5b2b72119fbb60750e0061ba")
,
"_id" : ObjectId("5b2b72329fbb60750e0061bb"),
"cost" : 250,
"serviceId" : ObjectId("5b24aff4abf2494701bc1c15"),
"time" : "03:30 PM - 04:30 PM",
"timeSlot_id" : ObjectId("5b29e08cb116c31f5b1f56c6"),
"date" : "21-06-2018"
],
"__v" : 0
服务
"_id" : ObjectId("5b24aff4abf2494701bc1c15"),
"isActivated" : true,
"supplierServiceId" : 900146649,
"serviceId" : 99473640,
"serviceName" : "AC Reparing",
"description" : "all type of AC, Split AC and Window AC",
"cost" : 250,
"serviceDuration" : "60",
"startTime" : "07:00 AM",
"endTime" : "08:30 PM",
"supplierId" : "5b221d1b63eda2902418434d",
"createdAt" : ISODate("2018-06-16T06:36:36.091Z"),
"__v" : 0
时隙
"_id" : ObjectId("5b29e08cb116c31f5b1f56c6"),
"displayString" : "03:30 PM - 04:30 PM",
"isActivated" : true,
"startTime" : "15:30 PM",
"endTime" : "16:30 PM",
"duration" : "60",
"createdAt" : ISODate("2018-06-20T05:05:16.405Z"),
"__v" : 0
CART 中的服务有两个值 serviceId 和 timeSlot_id
*我需要来自相关集合的与两者相关的数据。在同一个对象内。
Mongo 版本-v3.6.5
请帮助解决这个问题。提前致谢。
【问题讨论】:
【参考方案1】:您需要 $unwind
services
以便将其 timeSlot_id
和 serviceId
与另一个 TimeSlots 集合的 _id
和 ServiceId
分别匹配...然后您可以 $group
它开始“回滚”到数组中的过程。
如果你有 mongodb 版本 3.6
Cart.aggregate([
"$match": "user_id": _user._id ,
"$unwind": "$services" ,
"$lookup":
"from": TimeSlot.collection.name,
"let": "timeSlot_id": "$services.timeSlot_id" ,
"pipeline": [
"$match": "$expr": "$eq": [ "$_id", "$$timeSlot_id" ]
],
"as": "services.timeSlot_id"
,
"$lookup":
"from": Service.collection.name,
"let": "serviceId": "$services.serviceId" ,
"pipeline": [
"$match": "$expr": "$eq": [ "$_id", "$$serviceId" ]
],
"as": "services.serviceId"
,
"$unwind": "$services.timeSlot_id" ,
"$unwind": "$services.serviceId" ,
"$group":
"_id": "$_id",
"services": "$push": "$services" ,
"cartId" : "$first": "$cartId" ,
"supplierId" : "$first": "$supplierId" ,
"user_id" : "$first": "$user_id" ,
"createdAt" : "$first": "$createdAt"
])
如果您有 3.6
之前的 mongodb 版本Cart.aggregate([
"$match": "user_id": _user._id ,
"$unwind": "$services" ,
"$lookup":
"from": TimeSlot.collection.name,
"localField": "services.timeSlot_id",
"foreignField": "_id",
"as": "services.timeSlot_id",
,
"$lookup":
"from": Service.collection.name,
"localField": "services.serviceId",
"foreignField": "_id",
"as": "services.serviceId",
,
"$unwind": "$services.timeSlot_id" ,
"$unwind": "$services.serviceId" ,
"$group":
"_id": "$_id",
"services": "$push": "$services" ,
"cartId" : "$first": "$cartId" ,
"supplierId" : "$first": "$supplierId" ,
"user_id" : "$first": "$user_id" ,
"createdAt" : "$first": "$createdAt"
])
【讨论】:
嘿@Ashh 我赞成你的解决方案,它对我真的很有帮助。但是我想在这里添加一个场景,所以假设 serviceId 是可选的,在这种情况下会发生什么,它将只返回那些同时具有 serviceId 和 timeSlot_id 的数组元素,那么你有什么解决方案吗?我们如何克服这个问题,并且应该能够返回所有数组元素,即使任何键是可选的并且在对象内部不可用。 docs.mongodb.com/manual/reference/operator/aggregation/unwind/….... 在$unwind
上使用preserveNullAndEmptyArrays
以上是关于$lookup 嵌套对象数组的主要内容,如果未能解决你的问题,请参考以下文章
合并嵌套在数组 mongoose 中的对象内的 $lookup 值