如何使用 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 包含两个属性 trialStatuslastdispositioncode。您在 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 以不区分大小写的方式处理搜索。但是,它会因分析字段和未分析字段而异。分析的字段被标记化,文本字段默认被标记化。我们理想地在分析字段上使用 NESTsuffix 扩展方法,并在分析字段上获得精确匹配。关于他们的更多信息