How to $lookup by avoiding null values in mongodb aggregate

陌路散爱 提交于 2020-05-29 10:34:56

问题


In here i'm using $lookup to to a left join from other collections, the query works fine but when some records missing values it returns

errmsg : $in requires an array as a second argument, found: null

Heres the querying document structure :

{
 "no" : "2020921008981",
 "sale" : {
  "soldItems" : [
    {
        "itemId" : "5b55ac7f0550de00210a3b24", 
    },

    {
        "itemId" : "5b55ac7f0550de00215584re", 
    }
  ], 
 "bills" : [
    {
        "billNo" : "2020921053467", 
        "insurancePlanId" : "160", 
    },

    {
        "billNo" : "2020921053467", 
        "insurancePlanId" : "170", 
     }
   ],
   "visitIds" : [
   5b55ac7f0550de00210a3b24, 5b55ac7f0550de00210a3b24
   ]

  }
}

the query :

db.case.aggregate([
{
    $lookup: {
        from: "insurance",
        let: { ipids: "$sale.bill.insurancePlanId" },
        pipeline: [
            {
                $unwind: "$coveragePlans"
            },
            {
                $match: { $expr: { $in: ["$coveragePlans._id", "$$ipids"] } }
            },
            {
                $project: { _id: 0, name: 1 }
            }
        ],
        as: "insurances"
    }
},
{
    $lookup: {
        from: "item",
        let: { iid: "$salesOrder.purchaseItems.itemRefId" },
        pipeline: [
            {
                $match: {
                    $expr: {
                        $in: ["$_id", {
                            $map: {
                                input: "$$iid",
                                in: { $toObjectId: "$$this" }
                            }
                        }
                        ]
                    }
                }
            }
        ],
        as: "items"
      }
  }
])

insurance collection :

{ 
  "_id" : ObjectId("5b55aca20550de00210a6d25"), 
  "name" : "HIJKL" 
  "coveragePlans" : [
    {
      "_id" : "160", 
      "name" : "UVWZ", 
    }, 
    { 
    "_id" : "161", 
    "name" : "LMNO", 
    }
   ]
 },
{ 
  "_id" : ObjectId("5b55aca20550de00210a6d25"),  
  "name" : "WXYZ"
  "coveragePlans" : [
   {
    "_id" : "169", 
    "name" : "5ABC", 
   }, 
   { 
    "_id" : "170", 
    "name" : "4XYZ", 
    }
  ]
}

item collection :

{ 
  "_id" : ObjectId("5b55ac7f0550de00210a3b24"), 
  "code" : "ABCDE"
},
{ 
  "_id" : ObjectId("5b55ac7f0550de00215584re"), 
  "code" : "PQRST" 
}

How to avoid this and do null checks effectively before pipe-lining into the next stages? Tried with { $match: { "fieldName": { $exists: true, $ne: null } } } but it returns mongo error regarding the format. If its the way to go please mention the stage i should put that.. Thanks in advance


回答1:


You can get around that by not using $in.

It looks like this $map is executed separately for every document in the items collection. If you were to run the map in an $addFields stage, you could used the simple form of lookup to match the added field to _id, which would automagically handle missing, null, and array.

Remove the added field with a $project stage if necessary.

db.case.aggregate([
    {$lookup: {
        from: "insurance",
        let: { ipids: "$sale.bill.insurancePlanId" },
        pipeline: [
            {$unwind: "$coveragePlans"},
            {$match: { $expr: { $in: ["$coveragePlans._id", "$$ipids"] } }},
            {$project: { _id: 0, name: 1 }}
        ],
        as: "insurances"
    }}
    {$addFields:{
        matchArray:{$map: {
                       input: "$$iid",
                       in: { $toObjectId: "$$this" }
        }}
    }},
    {$lookup: {
        from: "item",
        localField: "matchArray",
        foreignField:"_id",
        as: "items"
    }},
    {$project:{
        arrayField: 0 
    }}
])



回答2:


You can use $ifNull operator

let: { ipids: {$ifNull:["$sale.bill.insurancePlanId", [] ]} },

EDIT: To skip empty "$salesOrder.purchaseItems.itemRefId" values

let: { iid: {$filter: {input:"$salesOrder.purchaseItems.itemRefId", cond:{$ne:["$$this", ""]}}} },


来源:https://stackoverflow.com/questions/61231005/how-to-lookup-by-avoiding-null-values-in-mongodb-aggregate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!