我有使用NEST进行过滤器聚合的要求。但是由于对此我不太了解,所以我做了以下工作:
class Program
{
static void Main(string[] args)
{
ISearchResponse<TestReportModel> searchResponse =
ConnectionToES.EsClient()
.Search<TestReportModel>
(s => s
.Index("feedbackdata")
.From(0)
.Size(50000)
.Query(q =>q.MatchAll())
);
var testRecords = searchResponse.Documents.ToList<TestReportModel>();
result = ComputeTrailGap(testRecords);
}
private static List<TestModel> ComputeTrailGap(List<TestReportModel> testRecords)
{
var objTestModel = new List<TestModel>();
var ptpDispositionCodes = new string[] { "PTP" };
var bptpDispositionCodes = new string[] { "BPTP","SBPTP" };
int gapResult = testRecords.Where(w => w.trailstatus == "Gap").Count();
var ptpResult = testRecords.Where(w => ptpDispositionCodes.Contains(w.lastdispositioncode)).ToList().Count();
var bptpResult = testRecords.Where(w => bptpDispositionCodes.Contains(w.lastdispositioncode)).ToList().Count();
objTestModel.Add(new TestModel { TrailStatus = "Gap", NoOfAccounts = gapResult });
objTestModel.Add(new TestModel { TrailStatus = "PTP", NoOfAccounts = ptpResult });
objTestModel.Add(new TestModel { TrailStatus = "BPTP", NoOfAccounts = bptpResult });
return objTestModel;
}
}
DTO
public class TestReportModel
{
public string trailstatus { get; set; }
public string lastdispositioncode { get; set; }
}
public class TestOutputAPIModel
{
public List<TestModel> TestModelDetail { get; set; }
}
public class TestModel
{
public string TrailStatus { get; set; }
public int NoOfAccounts { get; set; }
}
该程序有效,但可以确定我们仅通过NEST访问Elastic Search,其余的Aggregations / Filter则使用Lambda完成。
我想使用NEST框架执行整个操作(聚合/过滤器等),然后使用过滤器聚合将其放入TestModel中。
如何在NEST中构造DSL查询?
到目前为止,我已经能够达到以下要求,但计数为零。我的查询构造有什么问题?
var ptpDispositionCodes = new TermsQuery
{
IsVerbatim = true,
Field = "lastdispositioncode",
Terms = new string[] { "PTP" },
};
var bptpDispositionCodes = new TermsQuery
{
IsVerbatim = true,
Field = "lastdispositioncode",
Terms = new string[] { "BPTP" },
};
ISearchResponse<TestReportModel> searchResponse =
ConnectionToES.EsClient()
.Search<TestReportModel>
(s => s
.Index("feedbackdata")
.From(0)
.Size(50000)
.Query(q =>q.MatchAll())
.Aggregations(fa => fa
.Filter("ptp_aggs", f => f.Filter(fd => ptpDispositionCodes))
.Filter("bptp_aggs", f => f.Filter(fd => bptpDispositionCodes))
)
);
我发现你正在尝试对的类型进行搜索TestReportModel
。你的方法的总体结构似乎足够好。但是,附加到筛选器容器的查询存在问题。
你TestReportModel
包含两个属性trialStatus
和lastdispositioncode
。你正在将Field
属性设置为查询内部的描述terms
。这就是你将计数视为零的原因。你要在其上执行搜索的模型(反过来,你要在其上执行搜索的索引)没有属性description
,因此没有区别。NEST
或Elasticsearch,在这种情况下不会引发任何异常。而是返回零计数。Field
值应修改为lastdispositioncode
。
// Type on which the search is being performed.
// Response is of the type ISearchResponse<TestReportModel>
public class TestReportModel
{
public string trailstatus { get; set; }
public string lastdispositioncode { get; set; }
}
修改后的terms
查询如下
// Field is "lastdispositioncode" and not "description"
// You may amend the Terms field as applicable
var ptpDispositionCodes = new TermsQuery
{
IsVerbatim = true,
Field = "lastdispositioncode",
Terms = new string[] { "PTP" },
};
var bptpDispositionCodes = new TermsQuery
{
IsVerbatim = true,
Field = "lastdispositioncode",
Terms = new string[] { "BPTP", "SBPTP" },
};
由于似乎这些值lastdispositioncode
似乎取一个单词值(你的示例中为PTP或BPTP),所以我认为,是否对文档中的字段进行分析与否无关紧要。你可以从以下ISearchResponse<T>
类型进一步获取计数,如下所示
var ptpDocCount = ((Nest.SingleBucketAggregate)response.Aggregations["ptp_aggs"]).DocCount;
var bptpDocCount = ((Nest.SingleBucketAggregate)response.Aggregations["bptp_aggs"]).DocCount;
QueryContainer qc1 = new QueryContainerDescriptor<TestReportModel>()
.Bool(b => b.Must(m => m.Terms(t => t.Field(f => f.lastdispositioncode.Suffix("keyword"))
.Terms(new string[]{"ptp"}))));
QueryContainer qc2 = new QueryContainerDescriptor<TestReportModel>()
.Bool(b => b.Must(m => m.Terms(t => t.Field(f => f.lastdispositioncode.Suffix("keyword"))
.Terms(new string[]{"bptp", "sbptp"}))));
现在,可以将这些查询容器挂接到你的聚合中,如下所示
.Aggregations(aggs => aggs
.Filter("f1", f => f.Filter(f => qc1))
.Filter("f2", f => f.Filter(f => qc2)))
NEST
在这种情况下,客户端生成的聚合查询如下所示
"f1": {
"filter": {
"bool": {
"must": [
{
"terms": {
"lastdispositioncode.keyword": [
"bptp"
]
}
}
]
}
}
}
同样,回到搜索不区分大小写的情况,Elasticsearch以不区分大小写的方式处理搜索。但是,它取决于已分析字段与未分析字段的不同。默认情况下,对分析字段进行标记化,对文本字段进行标记化。我们理想地在分析场上使用suffix
扩展方法,并NEST
在分析场上获得精确匹配。在这里更多关于他们的信息
我现在已将“条款”值设为小写,以得到类似于“ ptp”或“ bptp”的结果。无论如何,使这种情况不区分大小写。我已经在下面尝试过,但是很幸运var ptpDispositionCodes = new TermsQuery {IsVerbatim = true,Field =“ lastdispositioncode” .Suffix(“ keyword”),Terms = new string [] {“ ptp”}}; 错误:无法将类型'object'隐式转换为'Nest.Field'。存在显式转换(您是否缺少演员表?)
看起来这与映射有关。Elastic不区分大小写(已分析字段和未分析字段之间的差异),默认情况下会分析文本字段。您的情况是什么映射?请显示映射。另外,对于您提到的错误,您可以显式键入(将其添加为答案的编辑)。
修改了答案,以包括关键字搜索。请注意在这种情况下使用查询容器。你应该能够看到通过生成查询
NEST
的内DebugInformation
响应的领域。另外,您还可以查看是否可以通过kibana进行任何terms
查询过滤查询。此外,还添加了有关analyzed
和周围环境的参考non-analyzed
。很大的帮助.... 1还有1个问题。假设我想先应用Group by(例如field1),然后对field2进行排序,然后获取最新记录(每个组的前1个记录),我想应用avobe代码。莫名其妙地不能。您能帮我吗?我已经更新了问题
@ priyanka.sarkar-鉴于问题的范围(以及长度)在不断增加,为了使帖子对其他读者清晰易懂,我建议您将有关排序的最新查询发布为一个单独的问题。你怎么看呢?