带有C#的MongoDB - 使用动态生成的谓词进行查询

时间:2014-01-30 15:22:30

标签: c# linq mongodb mongodb-.net-driver

我无法使用动态生成的谓词查询MongoDB数据库。

我试图查询的文档结构是:

{ 
    "_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
}

我正在尝试使用生成运行时的谓词进行查询,例如:

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)

当我尝试执行查询时,我收到错误:“Unsupported where clause: <InvocationExpression>。”

我无法找到Linq to Mongo是否能够从这样的表达式生成查询(我认为应该)。

所以我只是想做一些C#Mongo驱动程序不支持的事情,或者我没有生成谓词吗?我从another question看到我应该做的事情应该是可能的(理论上至少)。

我正在使用官方10gen驱动程序版本1.8.3

2 个答案:

答案 0 :(得分:4)

不确定它是mongodb的解决方案,但您是否可以尝试使用来自linqkit的AsExpandable()(由与PredicateBuilder相同的人制作)。

可以找到LinqKit(以及有关AsExpandable()的更多信息以及与PredicateBuilder的关系)here

答案 1 :(得分:1)

使用MongoDB查询构建器而不是翻译谓词两次:

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);

我更改了查询以使用$elemMatch,因为我觉得您希望在同一个数组元素上匹配careerIdcultureId。如果该假设错误,请相应地调整查询。