Details
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")