[CSHARP-2727] PredicateTranslator.TranslatePipelineContains fails to parse MethodCallExpression Created: 04/Sep/19  Updated: 28/Oct/23  Resolved: 22/Nov/22

Status: Closed
Project: C# Driver
Component/s: Linq
Affects Version/s: 2.8.0, 2.9.1
Fix Version/s: 2.18.0

Type: New Feature Priority: Major - P3
Reporter: Bohdan Kobel Assignee: Robert Stam
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows 10, Azure Cosmos DB Emulator.



 Description   

I need to perform search on the documents with a field in range of specific values.

Having following model:

public class Entity
{
        public BsonDocument Body { get; set; }
 
        [BsonIgnore] public JObject BodyJson => JObject.Parse(Body.ToJson());
 
        public string Caption { get; set; }
}

With counterpart in DB:

{
    "_id": {
        "$oid": "5c5ad9825404a952105a2c7b"
    },
    "Body": {
        "name": "Test1"
    },
    "Caption": "Entity created for testing purposes",
    "id": "5c5ad9825404a952105a2c7b",
    "_ts": 1566318353
}

 
This code works just fine:

Expression<Func<TypeDefinition, bool>> predicate = entity => new[] { "Test1", "Test2" }.Contains(entity.Caption);
 
IMongoDatabase.GetCollection<Entity>("entities").Find(predicate).ToListAsync();

But when I try to perform search on Body contained properties (as below) - ArgumentException is being thrown:

Expression<Func<TypeDefinition, bool>> predicate = entity => new[] { "Test1", "Test2" }.Contains((string)entity.Body["name"]);

Exception details:

System.ArgumentException: Unsupported filter: Contains(value(System.String[])).
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node)
at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry)
at MongoDB.Driver.MongoCollectionImpl`1.CreateFindOperation[TProjection](FilterDefinition`1 filter, FindOptions`2 options)
at MongoDB.Driver.MongoCollectionImpl`1.FindAsync[TProjection](IClientSessionHandle session, FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass43_0`1.<FindAsync>b__0(IClientSessionHandle session)
at MongoDB.Driver.MongoCollectionImpl`1.<UsingImplicitSessionAsync>d__101`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MongoDB.Driver.IAsyncCursorSourceExtensions.<ToListAsync>d__16`1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at MyProj.Repositories.EntitiesRepository.<GetLatestMinorVersionAsync>d__7.MoveNext() in C:\projects\MyProj\Repositories\EntitiesRepository.cs:line 125

Taking a brief glance at PredicateTranslator, discovered that TranslatePipelineContains accepts one side of expression only as IFieldExpression. But since I'm using BsonDocument's accessor to retrieve property - MethodCallExpression is being passed:
(System.String).Call ($entity.Body).get_Item("name")



 Comments   
Comment by Githook User [ 23/Nov/22 ]

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-2727: Skip test using $toString when testing against server 3.6.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/b85c2193231c566cdc2d80e299a2b6a3f8a29819

Comment by Robert Stam [ 22/Nov/22 ]

This issue has been fixed in the new LINQ provider (known as LINQ3), which was introduced in the 2.14 release.

Configure your MongoClientSettings to use LinqProvider.V3 if you want to use this functionality.

To configure a client to use the LINQ3 provider use code like the following

var connectionString = "mongodb://localhost";
var clientSettings = MongoClientSettings.FromConnectionString(connectionString);
clientSettings.LinqProvider = LinqProvider.V3;
var client = new MongoClient(clientSettings);

Comment by Githook User [ 22/Nov/22 ]

Author:

{'name': 'rstam', 'email': 'robert@robertstam.org', 'username': 'rstam'}

Message: CSHARP-2727: Verify that string cast and queries on BsonDocument work in LINQ3.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/0ca9e2d067b48b856f3f1df274403c284f428cf9

Generated at Wed Feb 07 21:43:23 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.