$cond and $and returns true in aggregation pipeline when it should not

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Done
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • ALL
    • Hide

      I am running the aggregation on the `tasks` collection and  $lookup for `leadInfo` from the `o8leadevents` collection.
      Here is the task object
      ```{
        "_id": "00QVL00000IOHi52AH",
        "pod": "Policy Scout WT",
        "externalIdentifier": "00QVL00000IOHi52AH",
        "salesforceIdLeadOwner": "0055e000006s1bgAAA",
        "leadTakenTimestamp":

      {     "$date": "2025-03-11T14:18:23.000Z"   }

      ,
        "billable": true,
        "phone": "8706234140",
        "leadStatus": "Application",
        "isDeleted": false,
        "lastName": "Gardner",
        "firstCallAdvocate": "0055e000006s1bgAAA",
        "gender": "Female",
        "city": "Monticello",
        "salesforceLeadOwnerName": "Julia Jatzlau",
        "leadCreatedTime":

      {     "$date": "2025-03-11T14:17:49.000Z"   }

      ,
        "channelType": "Warm Transfer",
        "createdOn":

      {     "$date": "2025-03-14T14:39:02.159Z"   }

      ,
        "firstCallResult": "Callback Scheduled",
        "lastCallResult": "Callback Scheduled",
        "advocateNote": "3/18 10:30am VAR!!!!",
        "email": "jennifergardner0475@gmail.com",
        "productFromAd": "sife",
        "timestamp":

      {     "$date": "2025-03-14T14:38:46.000Z"   }

      ,
        "firstCallTime":

      {     "$date": "2025-03-11T14:17:53.000Z"   }

      ,
        "stateFromAd": "AR",
        "carrierFromAd": "Colonial Penn",
        "currentPosition": "APPLICATION - Filling out application",
        "leadSource": "Policy Scout",
        "selfServe": false,
        "lastCallTime":

      {     "$date": "2025-03-11T14:41:42.000Z"   }

      ,
        "dateOfBirth": "1955-10-18",
        "winbackEmails": false,
        "version": "6.1.9",
        "lastCallAdvocate": "0055e000006s1bgAAA",
        "positionDetail": "APPLICATION - Future Scheduled Appointment",
        "zipcode": "71656",
        "firstName": "Frankie",
        "billableWarmTransfer": true,
        "name": "Frankie Gardner",
        "originatingQueue": "CNO Warm Transfer",
        "salesforceIdLastModifiedBy": "0054z00000B5Vy6AAF",
        "age": 69,

        "contactor": null

      }

      ```
      There are 2 important fields on the `leadInfo` object, `contactor` which is null and `billableWarmTransfer` which is true.

      Now here is my aggregation pipeline:
      ```
      [
        {
          $match:
            /**
             * query: The query in MQL.
             */
           

      {         externalIdentifier: "00TVL00000RAfSG2A1"       }

        },
        {
          $lookup:

      {       from: "o8leadevents",       localField: "leadExternalIdentifier",       foreignField: "externalIdentifier",       as: "leadInfo"     }

        },
        {
          $unwind:

      {       path: "$leadInfo",       preserveNullAndEmptyArrays: true     }

        },
        {
          $match: {
            leadInfo:

      {         $ne: null       }

          }
        },
        {
          $project: {
            id: "$externalIdentifier",
            product: "$leadInfo.productFromAd",
            billableWarmTransfer:
              "$leadInfo.billableWarmTransfer",
            advocateLevel: "Level 7",
            callType: {
              $cond: {
                if:

      {             $eq: ["$advocateLevel", "Level 1"]           }

      ,
                then: "CONTACT",
                else: {
                  $cond: {
                    if: {
                      $and: [
                       

      {                     $eq: [                       "$leadInfo.billableWarmTransfer",                       true                     ]                   }

      ,
                       

      {                     $ne: ["$leadInfo.contactor", null]                   }

                      ]
                    },
                    then: "Internal",
                    else: "Standard"
                  }
                }
              }
            },
            _id: 0
          }
        }
      ]
      ```

      The issue is on the `callType` field.
      In our case, as the `advocateLevel` is not `Level 1`, we need to check the second condition. "$leadInfo.billableWarmTransfer" is equal to true but `$leadInfo.contactor` is null, so we should go to the else condition with result `Standard`. However we get "Internal". I reproduce the same issue with using $switch operator.

      Now if I add another step $project to the pipeline, with exact same logic for `callType`. I get the right result!
      ```
      /**
       * specifications: The fields to
       *   include or exclude.
       */
      {
          callType: {
          $cond: {
            if:

      {         $eq: ["$advocateLevel", "Contactor"]       }

      ,
            then: "CONTACT",
            else: {
              $cond: {
                if: {
                  $and: [
                   

      {                 $eq: [                   "$leadInfo.billableWarmTransfer",                   true                 ]               }

      ,
                   

      {                 $ne: ["$contactor", null]               }

                  ]
                },
                then: "Internal WT",
                else: "Standard"
              }
            }
          }
        }
      }
      ```

       

      The result after adding this is `Standard`.

      Let me know if it makes sense or if you need additionnal informations

       

      Show
      I am running the aggregation on the `tasks` collection and  $lookup for `leadInfo` from the `o8leadevents` collection. Here is the task object ```{   "_id": "00QVL00000IOHi52AH",   "pod": "Policy Scout WT",   "externalIdentifier": "00QVL00000IOHi52AH",   "salesforceIdLeadOwner": "0055e000006s1bgAAA",   "leadTakenTimestamp": {     "$date": "2025-03-11T14:18:23.000Z"   } ,   "billable": true,   "phone": "8706234140",   "leadStatus": "Application",   "isDeleted": false,   "lastName": "Gardner",   "firstCallAdvocate": "0055e000006s1bgAAA",   "gender": "Female",   "city": "Monticello",   "salesforceLeadOwnerName": "Julia Jatzlau",   "leadCreatedTime": {     "$date": "2025-03-11T14:17:49.000Z"   } ,   "channelType": "Warm Transfer",   "createdOn": {     "$date": "2025-03-14T14:39:02.159Z"   } ,   "firstCallResult": "Callback Scheduled",   "lastCallResult": "Callback Scheduled",   "advocateNote": "3/18 10:30am VAR!!!!",   "email": "jennifergardner0475@gmail.com",   "productFromAd": "sife",   "timestamp": {     "$date": "2025-03-14T14:38:46.000Z"   } ,   "firstCallTime": {     "$date": "2025-03-11T14:17:53.000Z"   } ,   "stateFromAd": "AR",   "carrierFromAd": "Colonial Penn",   "currentPosition": "APPLICATION - Filling out application",   "leadSource": "Policy Scout",   "selfServe": false,   "lastCallTime": {     "$date": "2025-03-11T14:41:42.000Z"   } ,   "dateOfBirth": "1955-10-18",   "winbackEmails": false,   "version": "6.1.9",   "lastCallAdvocate": "0055e000006s1bgAAA",   "positionDetail": "APPLICATION - Future Scheduled Appointment",   "zipcode": "71656",   "firstName": "Frankie",   "billableWarmTransfer": true,   "name": "Frankie Gardner",   "originatingQueue": "CNO Warm Transfer",   "salesforceIdLastModifiedBy": "0054z00000B5Vy6AAF",   "age": 69,   "contactor": null } ``` There are 2 important fields on the `leadInfo` object, `contactor` which is null and `billableWarmTransfer` which is true. Now here is my aggregation pipeline: ``` [   {     $match:       /**        * query: The query in MQL.        */       {         externalIdentifier: "00TVL00000RAfSG2A1"       }   },   {     $lookup: {       from: "o8leadevents",       localField: "leadExternalIdentifier",       foreignField: "externalIdentifier",       as: "leadInfo"     }   },   {     $unwind: {       path: "$leadInfo",       preserveNullAndEmptyArrays: true     }   },   {     $match: {       leadInfo: {         $ne: null       }     }   },   {     $project: {       id: "$externalIdentifier",       product: "$leadInfo.productFromAd",       billableWarmTransfer:         "$leadInfo.billableWarmTransfer",       advocateLevel: "Level 7",       callType: {         $cond: {           if: {             $eq: ["$advocateLevel", "Level 1"]           } ,           then: "CONTACT",           else: {             $cond: {               if: {                 $and: [                   {                     $eq: [                       "$leadInfo.billableWarmTransfer",                       true                     ]                   } ,                   {                     $ne: ["$leadInfo.contactor", null]                   }                 ]               },               then: "Internal",               else: "Standard"             }           }         }       },       _id: 0     }   } ] ``` The issue is on the `callType` field. In our case, as the `advocateLevel` is not `Level 1`, we need to check the second condition. "$leadInfo.billableWarmTransfer" is equal to true but `$leadInfo.contactor` is null, so we should go to the else condition with result `Standard`. However we get "Internal". I reproduce the same issue with using $switch operator. Now if I add another step $project to the pipeline, with exact same logic for `callType`. I get the right result! ``` /**  * specifications: The fields to  *   include or exclude.  */ {     callType: {     $cond: {       if: {         $eq: ["$advocateLevel", "Contactor"]       } ,       then: "CONTACT",       else: {         $cond: {           if: {             $and: [               {                 $eq: [                   "$leadInfo.billableWarmTransfer",                   true                 ]               } ,               {                 $ne: ["$contactor", null]               }             ]           },           then: "Internal WT",           else: "Standard"         }       }     }   } } ```   The result after adding this is `Standard`. Let me know if it makes sense or if you need additionnal informations  
    • None
    • 3
    • None
    • None
    • None
    • None
    • None
    • None

      I am using Mongo DB atlas and was able to reproduce the issue on both version 7 and 8.

      I am running an aggegration pipeline, on the $project stage, for one field I use $cond and $and and it always returns true on a particular check even when the value is null.
      The weird thing is that if I run another $project stage right after this one, with the same condition for this particular fields, it works fine!
      I also manage to reproduce for a $switch operator.

            Assignee:
            Unassigned
            Reporter:
            Pierre Machaux
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: