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

LINQ3 provider compiles queries on boolean fields as {$expr:field}/{$nor:[{$expr:field}]}

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 2.19.0
    • Affects Version/s: None
    • Component/s: None
    • Labels:

      Summary

      The LINQ3 provider compiles queries on boolean fields as {$expr: "$field"}, rather than {<field>:<value>}, or at the very least $eq/$neq. Worse still, it compiles negative queries on boolean fields as {$nor:[{$expr: "$field"}]}.

      This stops these queries from using indexes and rewriting them all to use Builders<T> is annoying boilerplate, as the queries are obviously more complex than that on our production code.

      We migrated to the LINQ V3 provider because it can handle some queries that V2 could not compile, but I cannot remember specifically which queries in our codebase those were. This has had quite a negative impact on our query targetting, I have been rewriting our queries to a verbose combo of Builder<T> and strings.

      Please provide the version of the driver. If applicable, please provide the MongoDB server version and topology (standalone, replica set, or sharded cluster).

      This has been reproduced on 2.17.1 and 2.18.0, on .NET Core 3.1 and .NET 6.0.

      How to Reproduce

      I have attached a small repro project that illustrates the issue, and pasted the example outputs here as well:

       

      // Produces {"BoolField":true}
      var findFieldV2 = testV2.Find(x => x.BoolField).ToString();
      
      // Produces {"BoolProperty":true}
      var findPropertyV2 = testV2.Find(x => x.BoolProperty).ToString();
      
      // Produces {"BoolField":true}
      var findFieldBuilderV2 = testV2.Find(Builders<TestClass>.Filter.Eq(x => x.BoolField, true)).ToString();
      
      // Produces {"BoolProperty":true}
      var findPropertyBuilderV2 = testV2.Find(Builders<TestClass>.Filter.Eq(x => x.BoolProperty, true)).ToString();
      
      // Produces {"$expr":"$BoolField"}
      var findFieldV3 = testV3.Find(x => x.BoolField).ToString();
      
      // Produces {"BoolProperty":true}
      var findPropertyV3 = testV3.Find(x => x.BoolProperty).ToString();
      
      // Produces {"BoolField":true}
      var findFieldBuilderV3 = testV3.Find(Builders<TestClass>.Filter.Eq(x => x.BoolField, true)).ToString();
      
      // Produces {"BoolProperty":true}
      var findPropertyBuilderV3 = testV3.Find(Builders<TestClass>.Filter.Eq(x => x.BoolProperty, true)).ToString();
      
      // Produces {"BoolField":{"$ne":true}}
      var negFindFieldV2 = testV2.Find(x => !x.BoolField).ToString();
      
      // Produces {"BoolProperty":{"$ne":true}}
      var negFindPropertyV2 = testV2.Find(x => !x.BoolProperty).ToString();
      
      // Produces {"BoolField":false}
      var negFindFieldBuilderV2 = testV2.Find(Builders<TestClass>.Filter.Eq(x => x.BoolField, false)).ToString();
      
      // Produces {"BoolProperty":false}
      var negFindPropertyBuilderV2 = testV2.Find(Builders<TestClass>.Filter.Eq(x => x.BoolProperty, false)).ToString();
      
      // Produces {"$nor":[{"$expr":"$BoolField"}]}
      var negFindFieldV3 = testV3.Find(x => !x.BoolField).ToString();
      
      // Produces {"BoolProperty":{"$ne":true}}
      var negFindPropertyV3 = testV3.Find(x => !x.BoolProperty).ToString();
      
      // Produces {"BoolField":false}
      var negFindFieldBuilderV3 = testV3.Find(Builders<TestClass>.Filter.Eq(x => x.BoolField, false)).ToString();
      
      // Produces {"BoolProperty":false}
      var negFindPropertyBuilderV3 = testV3.Find(Builders<TestClass>.Filter.Eq(x => x.BoolProperty, false)).ToString();

       

        1. MongoBools-2.csproj
          0.5 kB
        2. MongoBools-2.sln
          1 kB
        3. MongoDBLinqV3BoolFieldRepro-2.cs
          3 kB

            Assignee:
            robert@mongodb.com Robert Stam
            Reporter:
            alkis@fortunefish.co.uk Alkis Tsapanidis
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: