如何使用 NEST 进行过滤器聚合?
How to make Filter Aggregations using NEST?
我需要使用 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,其余的聚合/过滤器是使用 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
。您在 terms
查询中将 Field
属性 设置为 description。这就是您看到计数为零的原因。您在其上执行搜索的模型(反过来是您在其上执行搜索的索引)没有 属性 description
,因此存在差异。 NEST
或 Elasticsearch,在这种情况下不会抛出任何异常。相反,它 returns 计数为零。 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 以不区分大小写的方式处理搜索。但是,它会因分析字段和未分析字段而异。分析的字段被标记化,文本字段默认被标记化。我们理想地在分析字段上使用 NEST
的 suffix
扩展方法,并在分析字段上获得精确匹配。关于他们的更多信息
我需要使用 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,其余的聚合/过滤器是使用 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
。您在 terms
查询中将 Field
属性 设置为 description。这就是您看到计数为零的原因。您在其上执行搜索的模型(反过来是您在其上执行搜索的索引)没有 属性 description
,因此存在差异。 NEST
或 Elasticsearch,在这种情况下不会抛出任何异常。相反,它 returns 计数为零。 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 以不区分大小写的方式处理搜索。但是,它会因分析字段和未分析字段而异。分析的字段被标记化,文本字段默认被标记化。我们理想地在分析字段上使用 NEST
的 suffix
扩展方法,并在分析字段上获得精确匹配。关于他们的更多信息