Reputation: 1266
I am having trouble querying a MongoDB database using a predicate which is dynamically generated.
The document structue i am trying to query on is:
{
"_id" : 3121 ,
"Active" : true ,
"CategoryId" : 1 ,
"Crci" : "IH" ,
"CultureId" : null ,
"DateUpdated" : {
"$date" : 1381916923120
} ,
"Description" : "National Careers Service: Actuary" ,
"Keywords" : "" ,
"MaxLevel" : null ,
"MinLevel" : null ,
"PhoneNumber" : " " ,
"Priority" : 1 ,
"Title" : "National Careers Service: Actuary" ,
"WebUrl" : "https://nationalcareersservice.direct.gov.uk/advice/planning/jobprofiles/Pages/actuary.aspx" ,
"CareerCultureExternalResources" : [
{
"CareerId" : 5 ,
"CultureId" : 1 ,
"DisplayOrder" : 1 ,
"ExternalResourceId" : 3121 ,
"Vgs" : null
}
] ,
"SubjectExternalResources" : [ ] ,
"LifestyleCategories" : null
}
And I am trying to query using at predicate which is generated a runtime E.g.:
Expression<Func<ExternalResourceView, bool>> predicate = predicateBuilder.True<ExternalResourceView>();
if (request.CultureId != null && request.CareerId != null) {
predicate = predicate.And(er => er.CareerCultureExternalResources.Any(ccer => ccer.CareerId == request.CareerId.Value && ccer.CultureId == request.CultureId.Value));
}
else if (request.SubjectAreaId != null && request.SubjectLevel != null && request.CultureId != null)
{
predicate = predicate.And(er => er.SubjectExternalResources.Any(ser => ser.SubjectAreaId == request.CareerId && ser.CultureId == request.CultureId));
}
IEnumerable<ExternalResourceView> matchingExternalResources = _externalResourceLibrary.AsQueryable().Where(predicate)
When I try and execute the query I get the error: "Unsupported where clause: <InvocationExpression>
."
I am unable to find if the Linq to Mongo is able to generate a query from such an expression or not (I think it should).
So am I just trying to do something that the C# Mongo driver doesn't support or am I not generating the predicate right? I have seen from another question that what I'm trying to do should be possible (in theory at least).
I am using the official 10gen driver ver 1.8.3
Upvotes: 1
Views: 4928
Reputation: 60493
Not sure it's a solution for mongodb, but could you try to use AsExpandable()
coming from linqkit (made by the same guy as PredicateBuilder).
LinqKit (and more info about AsExpandable()
and relation with PredicateBuilder
) can be found here
Upvotes: 4
Reputation: 46291
Use the MongoDB Query builder instead of translating the predicate twice:
using MongoDB.Driver.Builders;
List<IMongoQuery> queries = new List<IMongoQuery>();
if (request.CultureId != null && request.CareerId != null) {
queries.Add(
Query<Person>.ElemMatch<IDependent>(p => p.Dependents,
q => Query.And(
q.EQ(x => x.CareerId, request.CareerId),
q.EQ(x => x.CultureId, request.CultureId))));
}
// ... etc
// Final Query:
var query = Query.And(queries);
I changed the query to use an $elemMatch
, because I have the feeling you want to match both careerId
and cultureId
on the same array element. If that assumption is wrong, adjust the query accordingly.
Upvotes: 1