Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-5010

Handling C#-"null" with non existent fields in Expressions not intuitive when using IgnoreIfNullConvention

    • Type: Icon: Question Question
    • Resolution: Duplicate
    • Priority: Icon: Unknown Unknown
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Dotnet Drivers
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?

      You might recognized that the filters

      {
        potentiallyMissingField: null
      }
      

      and

      {
        $expr: {
          $eq: ['$potentiallyMissingField', null]
        }
      }
      

      do not return the same results when the field is not existent. Whereas the first filter returns all documents where the field is missing or has the null value, the second only returns the documents where the field is existent and null. Negated operators accordingly.

      The same is true if you use expressions in projections.

      If you use `IgnoreIfNullConvention` like we do, you might have a hard time to express the things with C# Driver because C# does not know undefined.

      While in filters you might use the Exists check as well, in projections or Linq it is not as easy.

       

      Consider the projection

      myCollection
          .Aggregate()
          .Project(x => new MyResultDocument
          {
              CountNonNullItems = x.Items.Count(x => x != null),
              IsRemoved = x.RemovedAt.HasValue,
          });
      

      you will get a $project stage

      {
          countNonNullItems: {
              $sum: {
                  $map: {
                      input: '$items',
                      in: {
                          $cond: {
                              if: {
                                  $ne: ['$$this', null]
                              },
                              then: 1,
                              else: 0
                          }
                      }
                  }
              }
          },
          isRemoved: {
              $ne: ['$removedAt', null]
          }
      }
      

      Which is not what you expect when writing the c# syntax.

       

      Currently we end up with weird expressions like

      myCollection
          .Aggregate()
          .Project(x => new MyResultDocument
          {
              CountNonNullItems = x.Items.Count(x => (x ?? null) != null),
              IsRemoved = (x.RemovedAt ?? null) != null,
          });
      

      which will add a

      { $ifNull: ['$removedAt', null] }
      

       

      Is there a way to handle == null with $lte and != null with $gt (because this is what gives you the expected results) if IgnoreIfNullConvention is used?

            Assignee:
            james.kovacs@mongodb.com James Kovacs
            Reporter:
            robin.kaulfuss@qualitybytes.de Robin Kaulfuß
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: