使用NEST C#在Elastic Search中使用多个索引进行全文本搜索

时间:2019-06-06 12:57:07

标签: c# elasticsearch nest

我正在尝试使用NEST Client搜索多个索引Elasticsearch,我只是点击以下链接
[stackover post] How to search inside multiple indices using Nest ElasticSearch? 唯一的区别是我的索引已经存在,但没有返回

示例代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Elasticsearch.Net;
using Nest;

namespace ElasticSearchDemo
{


    public class ExceptionData
    {
        public bool HasException { get; set; }
        public string ExceptionMessage { get; set; }
    }
    public class ElasticSearchResponse : ExceptionData
    {
        public ISearchResponse<dynamic> elasticSearchResponse { get; set; }
    }

    public class ComponentTypES
    {
        public string ComponentID { get; set; }
        public string Componentname { get; set; }
        public string Summary { get; set; }
    }

    public class ProjectTypES
    {
        public string ProjectID { get; set; }
        public string Projectname { get; set; }
        public string Summary { get; set; }
        public string Description { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            // calling the function
            var response = GetAllSearchResults("test", 0, 10);



        }

        public static ElasticClient GetElasticSearchCommonSearch()
        {
            ElasticClient elasticClient = null;
            try
            {
                const string strElasticSearchURL = "http://localhost:9200/";
                const string componentIndex = "componenttypeindex";
                const string projectIndex = "projecttypeindex";

                if (!string.IsNullOrEmpty(strElasticSearchURL))
                {
                    ConnectionSettings connectionSettings = new ConnectionSettings(new Uri(strElasticSearchURL))
                        .DefaultIndex(componentIndex)
                        .DefaultMappingFor<ComponentTypES>(i => i.IndexName(componentIndex).TypeName("Componenttype"))
                        .DefaultMappingFor<ProjectTypES>(j => j.IndexName(projectIndex).TypeName("Projecttype"))

                        .DisableDirectStreaming()
                        .PrettyJson()
                                .OnRequestCompleted(callDetails =>
                                {
                                    if (callDetails.RequestBodyInBytes != null)
                                    {
                                        Console.WriteLine(
                                            $"{callDetails.HttpMethod} {callDetails.Uri} \n" +
                                            $"{Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)}");
                                    }
                                    else
                                    {
                                        Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}");
                                    }

                                    Console.WriteLine();

                                    if (callDetails.ResponseBodyInBytes != null)
                                    {
                                        Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                                                 $"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" +
                                                 $"{new string('-', 30)}\n");
                                    }
                                    else
                                    {
                                        Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                                                 $"{new string('-', 30)}\n");
                                    }
                                }
                        );

                    elasticClient = new ElasticClient(connectionSettings);
                }

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message + "  ConnectionObject for : Common Search");
            }

            return elasticClient;
        }

        public static ElasticSearchResponse GetAllSearchResults(string query = "test", int
                                              page = 1, int pagesize = 10)
        {
            ElasticSearchResponse combinedResponse = new   ElasticSearchResponse();

            try
            {
                ElasticClient elasticClient =  GetElasticSearchCommonSearch();

                var clusterHealth = elasticClient.ClusterHealth();
                if (clusterHealth.IsValid && string.Compare(clusterHealth.Status.ToString(), "red", true) != 0 && clusterHealth.ServerError == null)
                {
                    string Componentindex = "componenttypeindex";
                    string Projectindex =  "projecttypeindex";

                    var indices = Indices.Index(typeof(ComponentTypES)).And(typeof(ProjectTypES));

                    //elasticClient.Refresh(indices);

                    //TODO : Development time coding 

                    if (null != (indices))
                    {
                        var indexExists = elasticClient.IndexExists(Indices.Index(Componentindex));
                        var projectExists = elasticClient.IndexExists(Indices.Index(Projectindex));

                        if (indexExists.Exists && indexExists.IsValid && projectExists.Exists && projectExists.IsValid)
                        {


                            //full text example 1

                            combinedResponse.elasticSearchResponse = elasticClient.Search<object>(s => s
                             .Index(indices)
                             .Type(Types.Type(typeof(ComponentTypES), typeof(ProjectTypES)))
                             .Query(q => (q
                             .MultiMatch(m => m
                              .Fields(f => f
                                      .Field(Infer.Field<ComponentTypES>(ff => ff.Componentname))
                                      .Field(Infer.Field<ComponentTypES>(ff => ff.Summary, 1.1))
                                        )
                              .Operator(Operator.Or)
                              .Query(query)
                                         ) && +q
                             .Term("_index", Componentindex)) || (q
                             .MultiMatch(m => m
                             .Fields(f => f
                                         .Field(Infer.Field<ProjectTypES>(ff => ff.Projectname))
                                         .Field(Infer.Field<ProjectTypES>(ff => ff.Summary, 0.3))
                              )
                              .Operator(Operator.Or)
                              .Query(query)
                               ) && +q
                                 .Term("_index", Projectindex))
                              ).From(page - 1)
                              .Size(pagesize)

                               );


                            //free text example 2
                            combinedResponse.elasticSearchResponse = elasticClient.Search<object>(s => s
                                                             .Index(indices)
                                                             .Type(Types.Type(typeof(ComponentTypES), typeof(ProjectTypES)))
                                                             .Query(q => (q
                                                                 .MatchPhrase(m => m
                                                                         .Field(Infer.Field<ComponentTypES>(ff => ff.Componentname))
                                                                         .Query(query)
                                                                 ) && +q
                                                                 .Term("_index", Componentindex)) || (q
                                                                 .MatchPhrase(m => m
                                                                     .Field(Infer.Field<ProjectTypES>(ff => ff.Projectname))
                                                                     .Query(query)
                                                                     )
                                                                 ) && +q
                                                                 .Term("_index", Projectindex)
                                                             ).From(page - 1)
                                                             .Size(pagesize)
                                                        );



                        }
                        else
                        {
                            combinedResponse.HasException = true;
                            combinedResponse.ExceptionMessage = "Index Not Found";
                        }
                    }
                    else
                    {
                        combinedResponse.HasException = true;
                        combinedResponse.ExceptionMessage = "Index Not Found In Config File";
                    }
                }
                else
                {
                    combinedResponse.HasException = true;
                    combinedResponse.ExceptionMessage = "Error on connecting with ElasticSearch";
                }
            }
            catch (Exception ex)
            {
                combinedResponse.HasException = true;
                combinedResponse.ExceptionMessage = ex.Message;
                return combinedResponse;
            }

            return combinedResponse;
        }


    }
}

弹性表架构:

PUT componenttypeindex
{
  "mappings": {
    "Componenttype":{
      "properties":{
        "ComponentID":{"type":"text"},
        "Componentname":{"type":"text"},
        "Summary":{"type":"text"}
           }
        }
    }
}

PUT projecttypeindex
{
  "mappings": {
    "Projecttype":{
      "properties":{
        "ProjectID":{"type":"text"},
        "Projectname":{"type":"text"},
        "Summary":{"type":"text"},
         "Description":{"type":"text"}
                }
            }
         }
}

它应该返回查询匹配项,但是什么也没有返回 抱歉,我尝试过难看的代码格式,但是新的编辑器不会更改任何内容

更新: 我已经按照@RussCam的建议更新了查询中的索引值,但仍然没有预期的结果,而且当展开响应对象并直接在浏览器中运行URI参数时,它的所有结果有些奇怪,不确定为什么未显示响应计数

通过在POST上成功进行的低级调用构建的有效NEST响应:/ componenttypeindex%2Cprojecttypeindex / Componenttype%2CProjecttype / _search?typed_keys = true

此API调用的审核记录:

URI =“ http://localhost:9200/componenttypeindex%2Cprojecttypeindex/Componenttype%2CProjecttype/_search?typed_keys=true

我的POCO课程:

public class ComponentTypES
{
    public string ComponentID { get; set; }
    public string Componentname { get; set; }
    public string Summary { get; set; }

}  

public class ProjectTypES
{

    public string ProjectID { get; set; }
    public string Projectname { get; set; }
    public string Summary { get; set; }
    public string Description { get; set; } 
}

样本数据:

PUT componenttypeindex/Componenttype/5342e739-1635-4021-baf2-55e25b95b8ec
{
    "ComponentID":"5342e739-1635-4021-baf2-55e25b95b8ec",
    "Componentname":"TestComponent1",
    "Summary":"this is summary of test component1"
}

PUT componenttypeindex/Componenttype/90781386-8065-11e9-bc42-526af7764f64
{    
    "ComponentID":"90781386-8065-11e9-bc42-526af7764f64",
    "Componentname":"TestComponent2",
    "Summary":"this is summary of test component3"  
}
PUT componenttypeindex/Componenttype/19871386-8065-11e9-bc42-526af7764f64
{
    "ComponentID":"19871386-8065-11e9-bc42-526af7764f64",
    "Componentname":"some xyz component test",
    "Summary":"this is summary test of test xyz"
}


PUT projecttypeindex/Projecttype/5342e739-2019-4021-baf2-55e25b95b8ec
{
        "ProjectID":"5342e739-2019-4021-baf2-55e25b95b8ec",
        "Projectname":"Test Project1",
        "Summary":"summary of Test Project1",
        "Description":"Description of TestProject1"
}

PUT projecttypeindex/Projecttype/5342f739-2019-4021-baf2-55e25b95b8ba
{
        "ProjectID":"5342f739-2019-4021-baf2-55e25b95b8ba",
        "Projectname":"Test Project2",
        "Summary":"summary of Test Project2",
        "Description":"Description of TestProject1"
}

PUT projecttypeindex/Projecttype/6342f739-2020-4021-baf2-55e25b95b8ac
{
        "ProjectID":"6342f739-2020-4021-baf2-55e25b95b8ac",
        "Projectname":"some PQRS project",
        "Summary":"summary of PQRS Project",
        "Description":"Description of PQORS Project1"
}

1 个答案:

答案 0 :(得分:1)

您的示例中有很多多余的信息,使操作起来很棘手,这增加了希望提供帮助的人所需要付出的努力。我是否可以建议您将示例缩减为最小,简洁但完整的示例,以说明您将来面临的问题;这确实有助于更快地解决问题的症结所在!

我认为根本的问题是索引映射的字段中的属性的大小写以及NEST默认发送的属性的大小写是不同的,因此{{1}中嵌套的must子句由于字段大小写不同,由NEST生成的should查询的}}子句绝不会与任何文档匹配。

NEST by default camel cases property names,但是示例中的索引映射和文档中的字段都是用pascal大小写的,因此NEST生成的字段名称将与映射中的字段名称不匹配。您可以使用bool上的DefaultFieldNameInferrer(Func<string, string>)方法来轻松更改NEST的现场套管行为。仅返回返回的字符串值的委托将保留字段名称,就像在POCO上一样。

这是一个完整而简洁的示例

ConnectionSettings

搜索得到的JSON查询是

private static void Main()
{
    const string componentIndex = "componenttypeindex";
    const string projectIndex = "projecttypeindex";

    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

    var settings = new ConnectionSettings(pool)
        .DefaultIndex(componentIndex)
        .DefaultMappingFor<ComponentTypES>(i => i.IndexName(componentIndex).TypeName("Componenttype").IdProperty(f => f.ComponentID))
        .DefaultMappingFor<ProjectTypES>(j => j.IndexName(projectIndex).TypeName("Projecttype").IdProperty(f => f.ProjectID))
        .DefaultFieldNameInferrer(f => f)
        .DefaultTypeName("_doc")
        .DisableDirectStreaming()
        .PrettyJson()
        .OnRequestCompleted(callDetails =>
        {
            if (callDetails.RequestBodyInBytes != null)
            {
                Console.WriteLine(
                    $"{callDetails.HttpMethod} {callDetails.Uri} \n" +
                    $"{Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)}");
            }
            else
            {
                Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}");
            }

            Console.WriteLine();

            if (callDetails.ResponseBodyInBytes != null)
            {
                Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                         $"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" +
                         $"{new string('-', 30)}\n");
            }
            else
            {
                Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                         $"{new string('-', 30)}\n");
            }
        });

    var client = new ElasticClient(settings);

    foreach (var index in new[] { componentIndex, projectIndex }) 
    {
        if (client.IndexExists(index).Exists)
            client.DeleteIndex(index);

        client.CreateIndex(index, c => c
            .Mappings(m => {
                if (index == projectIndex)
                    return m.Map<ProjectTypES>(mm => mm.AutoMap());
                else
                    return m.Map<ComponentTypES>(mm => mm.AutoMap());
            })
        );
    }

    client.Bulk(b => b
        .IndexMany(new [] {
            new ComponentTypES 
            {
                ComponentID = "5342e739-1635-4021-baf2-55e25b95b8ec",
                Componentname = "TestComponent1",
                Summary = "this is summary of test component1"
            },
            new ComponentTypES
            {
                ComponentID = "90781386-8065-11e9-bc42-526af7764f64",
                Componentname = "TestComponent2",
                Summary = "this is summary of test component3"
            },
            new ComponentTypES
            {
                ComponentID = "19871386-8065-11e9-bc42-526af7764f64",
                Componentname = "some xyz component test",
                Summary = "this is summary test of test xyz"
            },
        })
        .IndexMany(new [] {
            new ProjectTypES
            {
                ProjectID = "5342e739-2019-4021-baf2-55e25b95b8ec",
                Projectname = "Test Project1",
                Summary = "summary of Test Project1",
                Description = "Description of TestProject1"
            },
            new ProjectTypES
            {
                ProjectID = "5342f739-2019-4021-baf2-55e25b95b8ba",
                Projectname = "Test Project2",
                Summary = "summary of Test Project2",
                Description = "Description of TestProject1"
            },
            new ProjectTypES
            {
                ProjectID = "6342f739-2020-4021-baf2-55e25b95b8ac",
                Projectname = "some PQRS project",
                Summary = "summary of PQRS Project",
                Description = "Description of PQORS Project1"
            },
        })
        .Refresh(Refresh.WaitFor)
    );

    var query = "test";

    var response = client.Search<object>(s => s
        .Index(Indices.Index(typeof(ComponentTypES)).And(typeof(ProjectTypES)))
        .Type(Types.Type(typeof(ComponentTypES), typeof(ProjectTypES)))
        .Query(q => 
            (q
                .MultiMatch(m => m
                    .Fields(f => f
                        .Field(Infer.Field<ComponentTypES>(ff => ff.Componentname))
                        .Field(Infer.Field<ComponentTypES>(ff => ff.Summary, 1.1))
                    )
                    .Operator(Operator.Or)
                    .Query(query)
                ) && +q
                .Term("_index", componentIndex)
            ) || 
            (q
                .MultiMatch(m => m
                    .Fields(f => f
                        .Field(Infer.Field<ProjectTypES>(ff => ff.Projectname))
                        .Field(Infer.Field<ProjectTypES>(ff => ff.Summary, 0.3))
                    )
                    .Operator(Operator.Or)
                    .Query(query)
                ) && +q
                .Term("_index", projectIndex)
            )
        )
    );
}

public class ComponentTypES
{
    public string ComponentID { get; set; }
    public string Componentname { get; set; }
    public string Summary { get; set; }

}

public class ProjectTypES
{

    public string ProjectID { get; set; }
    public string Projectname { get; set; }
    public string Summary { get; set; }
    public string Description { get; set; }
}

返回5个结果

POST http://localhost:9200/componenttypeindex%2Cprojecttypeindex/Componenttype%2CProjecttype/_search?pretty=true&typed_keys=true 
{
  "query": {
    "bool": {
      "should": [
        {
          "bool": {
            "filter": [
              {
                "term": {
                  "_index": {
                    "value": "componenttypeindex"
                  }
                }
              }
            ],
            "must": [
              {
                "multi_match": {
                  "fields": [
                    "Componentname",
                    "Summary^1.1"
                  ],
                  "operator": "or",
                  "query": "test"
                }
              }
            ]
          }
        },
        {
          "bool": {
            "filter": [
              {
                "term": {
                  "_index": {
                    "value": "projecttypeindex"
                  }
                }
              }
            ],
            "must": [
              {
                "multi_match": {
                  "fields": [
                    "Projectname",
                    "Summary^0.3"
                  ],
                  "operator": "or",
                  "query": "test"
                }
              }
            ]
          }
        }
      ]
    }
  }
}
相关问题