如何在c#中使用函数/表达式创建查询对象
本文关键字:表达式 创建 查询 对象 函数 | 更新日期: 2023-09-27 18:02:18
我想为我的项目创建一个使用ElasticSearch的可重用查询对象。我已经使用类似的QueryObject从工作/存储库的通用单元LongLe查询数据库使用实体框架。
我似乎真的不知道该怎么做——我不确定如何将lambda表达式的各个部分"链接"在一起。我试过使用表达式/函数,但这对我来说是一个新的领域,我不完全理解。我觉得自己就像在黑暗中捅刀子一样。
由于我甚至不知道如何准确地表达我的问题,这里有一个例子,说明我目前正在做什么,我正在努力做什么,以及我到目前为止的进展:
我现在要做的:
ISearchResponse<DemoIndexModel> result = client.Search<DemoIndexModel>(s => s.Query(
q => q.Term(t => t.FirstName, firstName)
&& q.Term(t => t.LastName, lastName)));
我想做的:
var query = new DemoIndexQuery();
query = query.ByFirstName(firstName);
query = query.ByLastName(lastName);
result = client.Search<DemoIndexModel>(s => s.Query(query.Compile()));
目前代码:
public abstract class ElasticQueryObject<T> where T : class
{
private Func<QueryDescriptor<T>, QueryContainer> _query;
// tried using Expression, still completely lost
private Expression<Func<QueryDescriptor<T>, QueryContainer>> _expression;
public Func<QueryDescriptor<T>, QueryContainer> Compile()
{
return _query;
}
public Func<QueryDescriptor<T>, QueryContainer> And(Func<QueryDescriptor<T>, QueryContainer> query)
{
if (_query == null)
{
_query = query;
}
else
{
// how do I chain the query??? I only can figure out how to set it.
}
return null;
}
}
public class DemoIndexQuery : ElasticQueryObject<DemoIndexModel>
{
public DemoIndexQuery ByFirstName(string firstName)
{
And(p => p.Term(term => term.FirstName, firstName));
return this;
}
public DemoIndexQuery ByLastName(string lastName)
{
And(p => p.Term(term => term.LastName, lastName));
return this;
}
}
你违反了LINQ合同。查询应该是不可变的——对查询进行操作的所有方法都应该返回一个新的查询,而不是修改旧的查询。由于查询的构建方式,这在本质上是可组合的,所以不用
public DemoIndexQuery ByFirstName(string firstName)
{
And(p => p.Term(term => term.FirstName, firstName));
return this;
}
你可以这样写:
public DemoIndexQuery ByFirstName(string firstName)
{
return Where(p => p.Term(term => term.FirstName, firstName));
}
如果由于某种原因不能这样做,则需要在传递表达式树之前自己处理构建表达式树的问题。最简单的方法是这样的:
Expression<...> oldQuery = ...;
var newCondition = (Expression<...>)(p => p.Term(...));
return Expression.And(oldQuery, newCondition);
如果您的查询提供程序不支持这个,您将需要更多的工作—您可以自己单独构建整个where谓词,然后确保您修复了lambdas和lambda参数。