如何使用NEST进行过滤器聚合? [英] How to make Filter Aggregations using NEST?
问题描述
我需要使用NEST进行过滤器聚合.但是由于对此我不太了解,所以我做了以下内容:
I have a requirement for filter aggregations using NEST. But since I don't know much about this, I have made the below:
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,其余的聚合/过滤器使用Lambda完成.
This program works but as can be figure out that we are only accessing the Elastic Search via NEST and the rest of the Aggregations /Filter are done using Lambda.
我想使用NEST框架执行整个操作(聚合/过滤器等),然后使用过滤器聚合将其放入TestModel中.
I would like to perform the entire operation (Aggregations /Filter etc) using NEST framework and put it in the TestModel using filter aggregation.
如何在NEST内部构造DSL查询?
How can I construct the DSL query inside NEST?
到目前为止,我已经达到了以下标准,但计数为零.我的查询构造有什么问题?
I have been able to make the below so far but the count is zero. What is wrong in my query construction?
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
类型进行搜索.您的方法的总体结构似乎足够好.但是,附加到过滤器容器的查询会出现问题.
I see that you are trying to perform a search on the type of TestReportModel
. The overall structure of your approach seems good enough. However, there is a trouble with the queries that are being attached to your filter containers.
您的 TestReportModel
包含两个属性 trialStatus
和 lastdispositioncode
.您要在 terms
查询中将 Field
属性设置为 description .这就是您将计数视为零的原因.您要在其上进行搜索的模型(反过来,您要在其上进行搜索的索引)没有属性 description
,因此没有区别. NEST
或Elasticsearch,在这种情况下不会引发任何异常.而是返回零计数. Field
的值应修改为 lastdispositioncode
.
Your TestReportModel
contains two properties trialStatus
and lastdispositioncode
. You are setting the Field
property as description inside your terms
query. This is the reason that you are seeing the counts as zero. The model on which you are performing the search on (in turn the index that you are performing the search on) does not have a property description
and hence the difference. NEST
or Elasticsearch, in this case does not throw any exception. Instead, it returns count zero. Field
value should be modified to 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; }
}
修改的条款
查询如下
// 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>
类型获取计数,如下所示
Since it seems that the values to lastdispositioncode
seem to take a single word value (PTP or BPTP from your examples), I believe, it is not going to matter if the field in the doc is analyzed or not. You can further obtain the counts from the ISearchResponse<T>
type as shown below
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"}))));
现在可以将这些查询容器挂接到您的聚合中,如下所示
Now these query containers can be hooked to your aggregation as shown below
.Aggregations(aggs => aggs
.Filter("f1", f => f.Filter(f => qc1))
.Filter("f2", f => f.Filter(f => qc2)))
在这种情况下,由 NEST
客户端生成的聚合查询如下所示:
The queries for aggregations that are generated by the NEST
client in this case look like below
"f1": {
"filter": {
"bool": {
"must": [
{
"terms": {
"lastdispositioncode.keyword": [
"bptp"
]
}
}
]
}
}
}
此外,回到搜索不区分大小写的情况,Elasticsearch以不区分大小写的方式处理搜索.但是,它取决于分析的字段与未分析的字段.默认情况下,对分析字段进行标记化,对文本字段进行标记化.我们理想地在分析字段上使用 NEST
的后缀
扩展方法,并在分析字段上获得精确匹配.关于它们的更多信息此处
Also, coming back to the case of search being case-insensitive, Elasticsearch deals with search in a case-insensitive fashion. However, it varies depending on analyzed vs non-analyzed fields. Analyzed fields are tokenized and text fields are by default tokenized. We use the suffix
extension method of NEST
on analyzed fields ideally and to get an exact match on the analyzed field. More about them here
这篇关于如何使用NEST进行过滤器聚合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!