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

Linq: bad $elemMatch for discriminator of array field

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 2.2.4
    • Affects Version/s: 2.1.1
    • Component/s: Linq
    • Labels:
      None
    • Environment:
      x64 Windows 7 & Windows Server 2012 R2; possibly other Win versions.
    • Major Change

      Hello,
      After upgrading to 2.1.1, we've noticed a problem with one of the oldest LINQ queries in our system which no longer filtered down a set of results to what we needed but instead returned just about every document in the collection.

      After tinkering with the underlying issue for a bit, here's a short, self-contained example:

      Unable to find source-code formatter for language: program.cs. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yaml
      namespace CodePad
      {
          using System;
          using System.Linq;
          using MongoDB.Bson;
          using MongoDB.Bson.Serialization.Attributes;
          using MongoDB.Driver;
      
          [BsonKnownTypes(typeof(A), typeof(B), typeof(AA))]
          [BsonDiscriminator(RootClass = true)]
          public abstract class Base
          {
              public int[] Values { get; set; }
              public Thing[] Things { get; set; }
          }
      
          public class A : Base
          {
          }
      
          public class AA : A
          {
          }
      
          public class B : Base
          {
          }
      
          public class Container
          {
              public ObjectId Id { get; set; }
              public Base[] Records { get; set; }
          }
      
          public class Thing
          {
              public int Value { get; set; }
          }
      
          internal class Program
          {
              static void Main(string[] args)
              {
                  var coll = new MongoClient().GetDatabase("Example").GetCollection<Container>("Containers");
      
                  coll.DeleteManyAsync(Builders<Container>.Filter.Empty).Wait();
                  coll.InsertOneAsync(new Container{Records = new Base[]{new AA()}}).Wait();
      
                  var queryBad = coll.AsQueryable().Where(_ => _.Records.Any(r => r is A));
                  var queryGood1 = coll.AsQueryable().Where(_ => _.Records.Any(r => r.Values.Any(v => v > 3 && v < 56)));
                  var queryGood2 = coll.AsQueryable().Where(_ => _.Records.Any(r => r.Things.Any(t => t.Value > 3 && t.Value < 56)));
                  var queryGood3 = coll.AsQueryable().Where(_ => _.Records.Any(r => r.GetType() == typeof (A)));
      
                  Console.WriteLine(queryBad);
                  Console.WriteLine(queryGood1);
                  Console.WriteLine(queryGood2);
                  Console.WriteLine(queryGood3);
                  Console.ReadKey(true);
              }
          }
      }
      

      The above code results in the following output:

      aggregate([{ "$match" : { "Records" : { "$elemMatch" : { "._t" : "A" } } } }])
      aggregate([{ "$match" : { "Records.Values" : { "$elemMatch" : { "$gt" : 3, "$lt" : 56 } } } }])
      aggregate([{ "$match" : { "Records.Things" : { "$elemMatch" : { "Value" : { "$gt" : 3, "$lt" : 56 } } } } }])
      aggregate([{ "$match" : { "Records._t" : { "$size" : 2 }, "Records._t.0" : "Base", "Records._t.1" : "A" } }])
      

      The first query adds a spurious "." before "_t" which basically matches to nothing. I've attempted to trigger the same bug with other fields (array of primitive BSON numbers, array of objects, another query over the discriminator using GetType()) but I couldn't get it to manifest except for the "is" keyword.

      Please let me know if you need any more information.
      Thanks for your time!

            Assignee:
            craig.wilson@mongodb.com Craig Wilson
            Reporter:
            federicoce@moravia.com Federico Ceccatto
            Votes:
            2 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: