$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 中的服务有两个值 serviceIdtimeSlot_id

*我需要来自相关集合的与两者相关的数据。在同一个对象内。

Mongo 版本-v3.6.5

请帮助解决这个问题。提前致谢。

【问题讨论】:

【参考方案1】:

您需要 $unwind services 以便将其 timeSlot_idserviceId 与另一个 TimeSlots 集合的 _idServiceId 分别匹配...然后您可以 $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 值

mongoDB对嵌套对象数组的聚合查找

mongodb $查找带有投影的数组中的嵌套对象

如何仅在猫鼬中使用聚合填充嵌套在对象数组中的字段?

$lookup inside $lookup 在数组中的对象数组中

MongoDB在具有附加字段的对象数组上聚合$lookup