Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

mongoose - Conditional lookup with array of objects in mongodb

I have two collections, one is products and the other is orders I want to write aggregation in products to have the matching orders.

Products

[{
 "id": "738097c4-5c52-11eb-ae93-0242ac130002",
 "title": "test product",
 "description": "Amet dolor justo erat sadipscing at sed sit et labore..",
 "combos": ["738097c4", "738097c5"]
},
{
 "id": "923097c4-5c52-11eb-ae93-0242ac1300cj2",
 "title": "test product 2",
 "description": "Acjhz cjzh ouhcio cho ",
 "combos": ["94563097c4", "84097e5"]
}]

Orders

[
{
  "id": "ce943752-7040-4926-9c1a-350633f4331f",
  "items": [
    {
      "itemId": "738097c4-5c52-11eb-ae93-0242ac130002",
      "type": "product",
      "expiry": "2021-10-10"
    },
    {
      "itemId": "738097c4",
      "type": "combo",
      "expiry": "2021-12-10"
    }
  ]
},
{
  "id": "33c59dc4-c443-45a7-99c2-caba98f6d107",
  "items": [
    {
      "itemId": "738097c4-5c52-11eb-ae93-0242ac130002",
      "type": "product",
      "expiry": "2022-11-10"
    },
    {
      "itemId": "738097c5",
      "type": "combo",
      "expiry": "2020-10-10"
    }
  ]
}
]

Expected Output

Products

[{
 "id": "738097c4-5c52-11eb-ae93-0242ac130002",
 "title": "test product",
 "description": "Amet dolor justo erat sadipscing at sed sit et labore..",
 "combos": ["738097c4", "738097c5"],
 "orders": [
       {
        "id": "ce943752-7040-4926-9c1a-350633f4331f",
        "items": [
                 {
                  "itemId": "738097c4-5c52-11eb-ae93-0242ac130002",
                  "type": "product",
                  "expiry": "2021-10-10"
                 },
                 {
                  "itemId": "738097c4",
                  "type": "combo",
                  "expiry": "2021-12-10"
                 }]
       }].

},
{
 "id": "923097c4-5c52-11eb-ae93-0242ac1300cj2",
 "title": "test product 2",
 "description": "Acjhz cjzh ouhcio cho ",
 "combos": ["94563097c4", "84097e5"],
 "orders:: []
}]

Matching Condition

Orders.items.expiry should be greater than current time

AND

(Any of the Orders.items.itemId should match products.id

OR

Orders.items.itemId should present inside products.combos)

Please help me to get the solution

question from:https://stackoverflow.com/questions/65838462/conditional-lookup-with-array-of-objects-in-mongodb

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use $lookup to join collections

The script is

db.Order.aggregate(
    [{$addFields: {
      items: {
        $filter:{
          input:"$items",
          cond:{
            $gt:[{$toDate:"$$this.expiry"},new Date()]
          }
        }
      }
    }}, {$lookup: {
      from: 'Products',
      let:{itemIds:"$items.itemId"},
      pipeline:[
        {
          $match:{
            $expr:{
              $or:[
                  {$in:["$id","$$itemIds"]},
                  {$in:["$combos","$$itemIds"]}
                ]
            }
          }
        }
        ],
      as: 'join'
    }}]
)

Update 1

Since you need the output from products

[{$lookup: {
  from: 'Orders',
  let:{pId:"$id",comboArray:"$combos"},
  pipeline:[
    {$addFields: {
      items: {
        $filter:{
          input:"$items",
          cond:{
            $gt:[{$toDate:"$$this.expiry"},new Date()]
          }
        }
      }
    }},
   {
     $unwind:"$items"
   },
   {
      $match:{
        $expr:{
          $or:[
              {$eq:["$$pId","$items.itemId"]},
              {$in:["$items.itemId","$$comboArray"]}
            ]
        }
      }
    },
    {
      $replaceRoot:{
        newRoot:"$items"
      }
    }

       ],
  as: 'orders'
}}]

Working Mongo playground


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...