Как избежать возможного нулевого сценария ошибки ios в mongodb Aggregate - PullRequest
0 голосов
/ 16 апреля 2020

Я настроил довольно длинный агрегатный запрос mon go, чтобы объединить несколько коллекций mon go и преобразовать их в вывод набора строковых полей. Запрос работает нормально, пока существуют все необходимые значения (ie: ids), но он прерывается, когда встречает нулевые или пустые значения при выполнении поиска $.

Ниже приведена запрашиваемая коллекция PatientFile:

 {
    "no" : "2020921008981",
    "startDateTime" : ISODate("2020-04-01T05:19:02.263+0000")
    "saleId" : "5e8424464475140d19c6941b",
    "patientId" : "5e8424464475140d1955941b"
 }

продажа:

 {
    "_id" : ObjectId("5e8424464475140d19c6941b"),
    "invoices" : [
        {
          "billNumber" : "2020921053467", 
          "type" : "CREDIT",
          "insurancePlanId" : "160"
        },
        {
          "billNumber" : "2020921053469", 
          "type" : "DEBIT",
          "insurancePlanId" : "161"
        }
    ],
     "status" : "COMPLETE"
 }

страховая коллекция:

  { 
    "_id" : ObjectId("5b55aca20550de00210a6d25"), 
    "name" : "HIJKL" 
    "plans" : [
       {
         "_id" : "160", 
         "name" : "UVWZ", 
       }, 
       { 
         "_id" : "161", 
         "name" : "LMNO", 
       }
     ]
  }

коллекция пациентов :

{ 
  "_id" : ObjectId("5b55cc5c0550de00217ae0f3"),  
  "name" : "TAN NAI",
  "userId" : {
    "number" : "787333128H"
    }
}

Вот совокупный запрос:

  db.getCollection("patientFile").aggregate([
  { $match: { "startDateTime": { $gte: ISODate("2020-01-01T00:00:00.000Z"), 
                          $lt: ISODate("2020-05-01T00:00:00.000Z") } } },

  {
    $lookup:
        {
            from: "patient",
            let: { pid: "$patientId" },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $eq: ["$_id", { $toObjectId: "$$pid" }]
                        }
                    }
                },
                { "$project": { "name": 1, "userId.number": 1, "_id": 0 } }
            ],
            as: "patient"
        }
   },
   {
    $lookup:
        {
            from: "sale",
            let: { sid: "$saleId" },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $eq: ["$_id", { $toObjectId: "$$sid" }]
                        }
                    }
                }
            ],
            as: "sale"
        }
},

{ $unwind: "$sale" },
{ $unwind: "$patient" },

{
    $lookup: {
        from: "insurance",
        let: { pid: {$ifNull:["$sale.bill.insurancePlanId", [] ]} },
        pipeline: [
            {
                $unwind: "$plans"
            },
            {
                $match: { $expr: { $in: ["$plans._id", "$$pid"] } }
            },
            {
                $project: { _id: 0, name: 1 }
            }
        ],
        as: "insurances"
       }
  },

  { $match: { "insurances.name": { $exists: true, $ne: null } } },


  {
    $addFields: {

        invoice: {
            $reduce: {
                input:  {$ifNull:["$sale.bill.billNumber", [] ]},
                initialValue: "",
                in: {
                    $cond: [{ "$eq": ["$$value", ""] }, "$$this", { $concat: ["$$value", "\n", "$$this"] }]
                }
            }
        },
        insurances: {
            $reduce: {
                input:  {$ifNull:["$insurances.name", [] ]},
                initialValue: "",
                in: {
                    $cond: [{ "$eq": ["$$value", ""] }, "$$this", { $concat: ["$$value", "\n", "$$this"] }]
                }
             }
          }

       }
  },


  {
    "$project": {
        "startDateTime": 1,
        "patientName": "$patient.name",
        "invoice": 1,
        "insurances": 1
       }
     }

   ],

      { allowDiskUse: true }

 )

Ошибка:

Unable to execute the selected commands

Mongo Server error (MongoCommandException): Command failed with error 241 (ConversionFailure): 'Failed to parse objectId '' in $convert with no onError value: Invalid string length for parsing to OID, expected 24 but found 0' on server localhost:27017. 

The full response is:
 { 
    "ok" : 0.0, 
    "errmsg" : "Failed to parse objectId '' in $convert with no onError value: Invalid string length for parsing to OID, expected 24 but found 0", 
    "code" : NumberInt(241), 
    "codeName" : "ConversionFailure"
 }

В качестве решения, которое я нашел, использовал $ifNull, но эта ошибка сохраняется приходит. Что было бы лучшим шагом для этого сценария?

1 Ответ

1 голос
/ 16 апреля 2020

Я вижу пару способов:

  • Вместо преобразования строкового значения в ObjectId для проверки преобразуйте ObjectId в строку

    $match: {
        $expr: {
            $eq: [{$toString: "$_id"}, "$$pid" ]
        }
    }
    
  • Вместо помощника $toObjectId используйте $convert и укажите значения onError и / или onNull:

    $match: {
        $expr: {
            $eq: ["$_id", { $convert: {
                                   input: "$$pid",
                                   to: "objectId", 
                                   onError: {error:true},
                                   onNull: {isnull:true}
            }}]
        }
    }
    
...