隐藏

.net平台下c#操作ElasticSearch详解

发布:2023/1/16 14:15:17作者:管理员 来源:本站 浏览次数:384

前面我们讲解了关于ElasticSearch的安装配置,以及CRUD


本章我将讲解怎么使用c#操作ElasticSearch。


首先你需要一定的技术储备,比如:asp.net webapi,mvc,jsonp,knockout。这些知识在这里不再讲解,请自行Google。


项目DEMO介绍


搜索和索引功能我是以服务(webapi项目)方式提供的,在客户端(mvc项目)中的view视图中,直接使用ajax(jsonp格式)方式调用webapi,然后使用knockout绑定到table上的。


项目结构如图:


 


引入驱动


工欲善其事必先利其器,首先我们需要在Supernova.Webapi层中引入操作ElasticSearch的驱动dll PlainElastic.Net。


如图:


 


复制代码


public class ElasticSearchHelper

   {

       public static readonly ElasticSearchHelper Intance = new ElasticSearchHelper();

       private ElasticConnection Client;

       private ElasticSearchHelper()

       {


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


           Client = new ElasticConnection("localhost", 9200);




       }

       /// <summary>

       /// 数据索引

       /// </summary>      

       /// <param name="indexName">索引名称</param>

       /// <param name="indexType">索引类型</param>

       /// <param name="id">索引文档id,不能重复,如果重复则覆盖原先的</param>

       /// <param name="jsonDocument">要索引的文档,json格式</param>

       /// <returns></returns>

       public IndexResult Index(string indexName, string indexType, string id, string jsonDocument)

       {

           

           var serializer = new JsonNetSerializer();

           string cmd = new IndexCommand(indexName, indexType, id);

           OperationResult result = Client.Put(cmd, jsonDocument);


           var indexResult = serializer.ToIndexResult(result.Result);

           return indexResult;

       }

       public IndexResult Index(string indexName, string indexType, string id, object document)

       {

           var serializer = new JsonNetSerializer();

           var jsonDocument = serializer.Serialize(document);

           return Index(indexName, indexType, id, jsonDocument);

       }


       //全文检索,单个字段或者多字段 或关系

       //字段intro 包含词组key中的任意一个单词

       //

       public personList Search<person>(string indexName, string indexType, string key,int from ,int size)

       {

           string cmd = new SearchCommand(indexName, indexType);

           string query = new QueryBuilder<person>()

               //1 查询

               .Query(b =>

                           b.Bool(m =>

                               //并且关系

                               m.Must(t =>


                                   //分词的最小单位或关系查询

                                  t.QueryString(t1=>t1.DefaultField("intro").Query(key))

                                  //.QueryString(t1 => t1.DefaultField("name").Query(key))

                                  // t .Terms(t2=>t2.Field("intro").Values("研究","方鸿渐"))

                                  //范围查询

                                   // .Range(r =>  r.Field("age").From("100").To("200") )  

                                    )

                                 )

                               )

                 //分页

                .From(from)

                .Size(size)

                //排序

               // .Sort(c => c.Field("age", SortDirection.desc))

                 //添加高亮

                 .Highlight(h => h

                     .PreTags("<b>")

                     .PostTags("</b>")

                     .Fields(

                            f => f.FieldName("intro").Order(HighlightOrder.score),

                            f => f.FieldName("_all")

                            )

                    )

                   .Build();



           string result = Client.Post(cmd, query);

           var serializer = new JsonNetSerializer();

           var list = serializer.ToSearchResult<Supernova.Webapi.DbHelper.person>(result);

           personList datalist = new personList();

           datalist.hits = list.hits.total;

           datalist.took = list.took;

            var personList= list.hits.hits.Select(c => new Supernova.Webapi.DbHelper.person() {

                id=c._source.id,

                age=c._source.age,

                birthday =c._source.birthday,

                intro=string.Join("",c.highlight["intro"]), //高亮显示的内容,一条记录中出现了几次

                name=c._source.name,

                sex=c._source.sex,

               

            });

            datalist.list.AddRange(personList);

            return  datalist;



       }


       //全文检索,多字段 并关系

       //字段intro 或者name 包含词组key

       public personList SearchFullFileds<person>(string indexName, string indexType, string key, int from, int size)

       {

           MustQuery<person> mustNameQueryKeys = new MustQuery<person>();

           MustQuery<person> mustIntroQueryKeys = new MustQuery<person>();

           var arrKeys = GetIKTokenFromStr(key);

           foreach (var item in arrKeys)

           {

               mustNameQueryKeys = mustNameQueryKeys.Term(t3 => t3.Field("name").Value(item)) as MustQuery<person>;

               mustIntroQueryKeys = mustIntroQueryKeys.Term(t3 => t3.Field("intro").Value(item)) as MustQuery<person>;

           }

           

           string cmd = new SearchCommand(indexName, indexType);

           string query = new QueryBuilder<person>()

               //1 查询

               .Query(b =>

                           b.Bool(m =>

                               m.Should(t =>  

                                        t.Bool(m1 =>

                                                    m1.Must(

                                                            t2 =>

                                                                //t2.Term(t3=>t3.Field("name").Value("研究"))

                                                                //   .Term(t3=>t3.Field("name").Value("方鸿渐"))  

                                                                mustNameQueryKeys

                                                            )

                                               )

                                      )

                              .Should(t =>

                                        t.Bool(m1 =>

                                                    m1.Must(t2 =>

                                                                    //t2.Term(t3 => t3.Field("intro").Value("研究"))

                                                                    //.Term(t3 => t3.Field("intro").Value("方鸿渐"))  

                                                                    mustIntroQueryKeys

                                                           )

                                               )

                                     )

                                 )

                       )

               //分页

                .From(from)

                .Size(size)

               //排序

               // .Sort(c => c.Field("age", SortDirection.desc))

               //添加高亮

                 .Highlight(h => h

                     .PreTags("<b>")

                     .PostTags("</b>")

                     .Fields(

                            f => f.FieldName("intro").Order(HighlightOrder.score),

                             f => f.FieldName("name").Order(HighlightOrder.score)

                            )

                    )

                   .Build();



           string result = Client.Post(cmd, query);

           var serializer = new JsonNetSerializer();

           var list = serializer.ToSearchResult<Supernova.Webapi.DbHelper.person>(result);

           personList datalist = new personList();

           datalist.hits = list.hits.total;

           datalist.took = list.took;

           var personList = list.hits.hits.Select(c => new Supernova.Webapi.DbHelper.person()

           {

               id = c._source.id,

               age = c._source.age,

               birthday = c._source.birthday,

               intro = c.highlight==null||!c.highlight.Keys.Contains("intro") ? c._source.intro : string.Join("", c.highlight["intro"]), //高亮显示的内容,一条记录中出现了几次

               name = c.highlight==null||!c.highlight.Keys.Contains("name") ? c._source.name : string.Join("", c.highlight["name"]),

               sex = c._source.sex


           });

           datalist.list.AddRange(personList);

           return datalist;



       }


       //全文检索,多字段 并关系

       //搜索age在100到200之间,并且字段intro 或者name 包含词组key

       public personList SearchFullFiledss<person>(string indexName, string indexType, string key, int from, int size)

       {

           MustQuery<person> mustNameQueryKeys = new MustQuery<person>();

           MustQuery<person> mustIntroQueryKeys = new MustQuery<person>();

           var arrKeys = GetIKTokenFromStr(key);

           foreach (var item in arrKeys)

           {

               mustNameQueryKeys = mustNameQueryKeys.Term(t3 => t3.Field("name").Value(item)) as MustQuery<person>;

               mustIntroQueryKeys = mustIntroQueryKeys.Term(t3 => t3.Field("intro").Value(item)) as MustQuery<person>;

           }


           string cmd = new SearchCommand(indexName, indexType);

           string query = new QueryBuilder<person>()

               //1 查询

               .Query(b =>

                           b.Bool(m =>

                               m.Must(t =>

                                         t.Range(r => r.Field("age").From("1").To("500"))

                                         .Bool(ms =>

                                                   ms.Should(ts =>  

                                                            ts.Bool(m1 =>

                                                                        m1.Must(

                                                                                t2 =>

                                                                                    //t2.Term(t3=>t3.Field("name").Value("研究"))

                                                                                    //   .Term(t3=>t3.Field("name").Value("方鸿渐"))  

                                                                                    //

                                                                                     mustNameQueryKeys

                                                                                )

                                                                   )

                                                          )

                                                  .Should(ts =>

                                                            ts.Bool(m1 =>

                                                                        m1.Must(t2 =>

                                                                                        //t2.Term(t3 => t3.Field("intro").Value("研究"))

                                                                                        //.Term(t3 => t3.Field("intro").Value("方鸿渐"))  

                                                                                       

                                                                                       //

                                                                                       mustIntroQueryKeys

                                                                               )

                                                                   )

                                                         )

                                                     )

                                                       )      

                                                     )

                      )

               //分页

                .From(from)

                .Size(size)

               //排序

               // .Sort(c => c.Field("age", SortDirection.desc))

               //添加高亮

                 .Highlight(h => h

                     .PreTags("<b>")

                     .PostTags("</b>")

                     .Fields(

                            f => f.FieldName("intro").Order(HighlightOrder.score),

                             f => f.FieldName("name").Order(HighlightOrder.score)

                            )

                    )

                   .Build();



           string result = Client.Post(cmd, query);

           var serializer = new JsonNetSerializer();

           var list = serializer.ToSearchResult<Supernova.Webapi.DbHelper.person>(result);

           personList datalist = new personList();

           datalist.hits = list.hits.total;

           datalist.took = list.took;

           var personList = list.hits.hits.Select(c => new Supernova.Webapi.DbHelper.person()

           {

               id = c._source.id,

               age = c._source.age,

               birthday = c._source.birthday,

               intro = c.highlight==null||!c.highlight.Keys.Contains("intro") ? c._source.intro : string.Join("", c.highlight["intro"]), //高亮显示的内容,一条记录中出现了几次

               name = c.highlight==null||!c.highlight.Keys.Contains("name") ? c._source.name : string.Join("", c.highlight["name"]),

               sex = c._source.sex


           });

           datalist.list.AddRange(personList);

           return datalist;



       }

       //分词映射

       private static string BuildCompanyMapping()

       {

           return new MapBuilder<person>()

               .RootObject(typeName: "person",

                           map: r => r

                   .All(a => a.Enabled(false))

                   .Dynamic(false)

                   .Properties(pr => pr

                       .String(person => person.name, f => f.Analyzer(DefaultAnalyzers.standard).Boost(2))

                       .String(person => person.intro, f => f.Analyzer("ik"))

                       )

             )

             .BuildBeautified();

       }


       //将语句用ik分词,返回分词结果的集合

       private List<string> GetIKTokenFromStr(string key)

       {

           string s = "/db_test/_analyze?analyzer=ik";

           var result = Client.Post(s, "{"+key+"}");

           var serializer = new JsonNetSerializer();

           var list = serializer.Deserialize(result, typeof(ik)) as ik;            

           return list.tokens.Select(c=>c.token).ToList();

       }



   }


复制代码


demo中涉及的实体对象模型

复制代码


/// <summary>

   /// ik分词结果对象

   /// </summary>

   public class ik

   {

       public List<tokens> tokens { get; set; }

   }

   public class tokens

   {

       public string token { get; set; }

       public int start_offset { get; set; }

       public int end_offset { get; set; }

       public string type { get; set; }

       public int position { get; set; }

   }


   /// <summary>

   /// 测试数据对象

   /// </summary>

   public class personList

   {

       public personList()

       {

           this.list = new List<person>();

       }

       public int hits { get; set; }

       public int took { get; set; }

       public List<person> list { get; set; }

   }

   public class person

   {

       public string id { get; set; }

       public string name { get; set; }

       public int age { get; set; }

       public bool sex { get; set; }

       public DateTime birthday { get; set; }

       public string intro { get; set; }

   }


复制代码


 


详细介绍ElasticSearchHelper里面的方法


1.索引文档(注意:索引文档之前先用配置filed对应的ik分词):

复制代码


public IndexResult Index(string indexName, string indexType, string id, string jsonDocument)

       {

           

           var serializer = new JsonNetSerializer();

           string cmd = new IndexCommand(indexName, indexType, id);

           OperationResult result = Client.Put(cmd, jsonDocument);


           var indexResult = serializer.ToIndexResult(result.Result);

           return indexResult;

       }

       public IndexResult Index(string indexName, string indexType, string id, object document)

       {

           var serializer = new JsonNetSerializer();

           var jsonDocument = serializer.Serialize(document);

           return Index(indexName, indexType, id, jsonDocument);

       }


复制代码


2.对单个字段的全文检索,字段intro 包含词组key中的任意一个单词。例如:词组(中国美好),只要每条数据的intro字段包含"中国"或者"美好"就返回。

复制代码


public personList Search<person>(string indexName, string indexType, string key,int from ,int size)

       {

           string cmd = new SearchCommand(indexName, indexType);

           string query = new QueryBuilder<person>()

               //1 查询

               .Query(b =>

                           b.Bool(m =>

                               //并且关系

                               m.Must(t =>


                                   //分词的最小单位或关系查询

                                  t.QueryString(t1=>t1.DefaultField("intro").Query(key))

                                  //.QueryString(t1 => t1.DefaultField("name").Query(key))

                                  // t .Terms(t2=>t2.Field("intro").Values("研究","方鸿渐"))

                                  //范围查询

                                   // .Range(r =>  r.Field("age").From("100").To("200") )  

                                    )

                                 )

                               )

                 //分页

                .From(from)

                .Size(size)

                //排序

               // .Sort(c => c.Field("age", SortDirection.desc))

                 //添加高亮

                 .Highlight(h => h

                     .PreTags("<b>")

                     .PostTags("</b>")

                     .Fields(

                            f => f.FieldName("intro").Order(HighlightOrder.score),

                            f => f.FieldName("_all")

                            )

                    )

                   .Build();



           string result = Client.Post(cmd, query);

           var serializer = new JsonNetSerializer();

           var list = serializer.ToSearchResult<Supernova.Webapi.DbHelper.person>(result);

           personList datalist = new personList();

           datalist.hits = list.hits.total;

           datalist.took = list.took;

            var personList= list.hits.hits.Select(c => new Supernova.Webapi.DbHelper.person() {

                id=c._source.id,

                age=c._source.age,

                birthday =c._source.birthday,

                intro=string.Join("",c.highlight["intro"]), //高亮显示的内容,一条记录中出现了几次

                name=c._source.name,

                sex=c._source.sex,

               

            });

            datalist.list.AddRange(personList);

            return  datalist;



       }


复制代码


 


3.字段intro 或者name 包含词组key中的所有单词。例如:词组(中国美好),只要每条数据的intro或者name字段包含"中国"并且包含"美好"就返回。

复制代码


  public personList SearchFullFileds<person>(string indexName, string indexType, string key, int from, int size)

       {

           MustQuery<person> mustNameQueryKeys = new MustQuery<person>();

           MustQuery<person> mustIntroQueryKeys = new MustQuery<person>();

           var arrKeys = GetIKTokenFromStr(key);

           foreach (var item in arrKeys)

           {

               mustNameQueryKeys = mustNameQueryKeys.Term(t3 => t3.Field("name").Value(item)) as MustQuery<person>;

               mustIntroQueryKeys = mustIntroQueryKeys.Term(t3 => t3.Field("intro").Value(item)) as MustQuery<person>;

           }

           

           string cmd = new SearchCommand(indexName, indexType);

           string query = new QueryBuilder<person>()

               //1 查询

               .Query(b =>

                           b.Bool(m =>

                               m.Should(t =>  

                                        t.Bool(m1 =>

                                                    m1.Must(

                                                            t2 =>

                                                                //t2.Term(t3=>t3.Field("name").Value("研究"))

                                                                //   .Term(t3=>t3.Field("name").Value("方鸿渐"))  

                                                                mustNameQueryKeys

                                                            )

                                               )

                                      )

                              .Should(t =>

                                        t.Bool(m1 =>

                                                    m1.Must(t2 =>

                                                                    //t2.Term(t3 => t3.Field("intro").Value("研究"))

                                                                    //.Term(t3 => t3.Field("intro").Value("方鸿渐"))  

                                                                    mustIntroQueryKeys

                                                           )

                                               )

                                     )

                                 )

                       )

               //分页

                .From(from)

                .Size(size)

               //排序

               // .Sort(c => c.Field("age", SortDirection.desc))

               //添加高亮

                 .Highlight(h => h

                     .PreTags("<b>")

                     .PostTags("</b>")

                     .Fields(

                            f => f.FieldName("intro").Order(HighlightOrder.score),

                             f => f.FieldName("name").Order(HighlightOrder.score)

                            )

                    )

                   .Build();



           string result = Client.Post(cmd, query);

           var serializer = new JsonNetSerializer();

           var list = serializer.ToSearchResult<Supernova.Webapi.DbHelper.person>(result);

           personList datalist = new personList();

           datalist.hits = list.hits.total;

           datalist.took = list.took;

           var personList = list.hits.hits.Select(c => new Supernova.Webapi.DbHelper.person()

           {

               id = c._source.id,

               age = c._source.age,

               birthday = c._source.birthday,

               intro = c.highlight==null||!c.highlight.Keys.Contains("intro") ? c._source.intro : string.Join("", c.highlight["intro"]), //高亮显示的内容,一条记录中出现了几次

               name = c.highlight==null||!c.highlight.Keys.Contains("name") ? c._source.name : string.Join("", c.highlight["name"]),

               sex = c._source.sex


           });

           datalist.list.AddRange(personList);

           return datalist;



       }


复制代码


 


3.搜索age在1到500之间,并且字段intro 或者name 包含词组key中的所有单词。

复制代码


public personList SearchFullFiledss<person>(string indexName, string indexType, string key, int from, int size)

       {

           MustQuery<person> mustNameQueryKeys = new MustQuery<person>();

           MustQuery<person> mustIntroQueryKeys = new MustQuery<person>();

           var arrKeys = GetIKTokenFromStr(key);

           foreach (var item in arrKeys)

           {

               mustNameQueryKeys = mustNameQueryKeys.Term(t3 => t3.Field("name").Value(item)) as MustQuery<person>;

               mustIntroQueryKeys = mustIntroQueryKeys.Term(t3 => t3.Field("intro").Value(item)) as MustQuery<person>;

           }


           string cmd = new SearchCommand(indexName, indexType);

           string query = new QueryBuilder<person>()

               //1 查询

               .Query(b =>

                           b.Bool(m =>

                               m.Must(t =>

                                         t.Range(r => r.Field("age").From("1").To("500"))

                                         .Bool(ms =>

                                                   ms.Should(ts =>  

                                                            ts.Bool(m1 =>

                                                                        m1.Must(

                                                                                t2 =>

                                                                                    //t2.Term(t3=>t3.Field("name").Value("研究"))

                                                                                    //   .Term(t3=>t3.Field("name").Value("方鸿渐"))  

                                                                                    //

                                                                                     mustNameQueryKeys

                                                                                )

                                                                   )

                                                          )

                                                  .Should(ts =>

                                                            ts.Bool(m1 =>

                                                                        m1.Must(t2 =>

                                                                                        //t2.Term(t3 => t3.Field("intro").Value("研究"))

                                                                                        //.Term(t3 => t3.Field("intro").Value("方鸿渐"))  

                                                                                       

                                                                                       //

                                                                                       mustIntroQueryKeys

                                                                               )

                                                                   )

                                                         )

                                                     )

                                                       )      

                                                     )

                      )

               //分页

                .From(from)

                .Size(size)

               //排序

               // .Sort(c => c.Field("age", SortDirection.desc))

               //添加高亮

                 .Highlight(h => h

                     .PreTags("<b>")

                     .PostTags("</b>")

                     .Fields(

                            f => f.FieldName("intro").Order(HighlightOrder.score),

                             f => f.FieldName("name").Order(HighlightOrder.score)

                            )

                    )

                   .Build();



           string result = Client.Post(cmd, query);

           var serializer = new JsonNetSerializer();

           var list = serializer.ToSearchResult<Supernova.Webapi.DbHelper.person>(result);

           personList datalist = new personList();

           datalist.hits = list.hits.total;

           datalist.took = list.took;

           var personList = list.hits.hits.Select(c => new Supernova.Webapi.DbHelper.person()

           {

               id = c._source.id,

               age = c._source.age,

               birthday = c._source.birthday,

               intro = c.highlight==null||!c.highlight.Keys.Contains("intro") ? c._source.intro : string.Join("", c.highlight["intro"]), //高亮显示的内容,一条记录中出现了几次

               name = c.highlight==null||!c.highlight.Keys.Contains("name") ? c._source.name : string.Join("", c.highlight["name"]),

               sex = c._source.sex


           });

           datalist.list.AddRange(personList);

           return datalist;



       }


复制代码


需要用到的方法:将语句用ik分词,返回分词结果的集合

复制代码


private List<string> GetIKTokenFromStr(string key)

       {

           string s = "/db_test/_analyze?analyzer=ik";

           var result = Client.Post(s, "{"+key+"}");

           var serializer = new JsonNetSerializer();

           var list = serializer.Deserialize(result, typeof(ik)) as ik;            

           return list.tokens.Select(c=>c.token).ToList();

       }


复制代码


 


ASP.NET WebApi 调用ElasticSearchHelper


1.首先我们添加一个基类ApiController

复制代码


public class BaseApiController : ApiController

   {


       public MongoDatabase db;

       public MongoCollection col = null;//用于直接返回查询的json      

       public BaseApiController() { }

       public BaseApiController(string collectionName)

       {

           db = DbHelper.MongodbHelper.Instance.DB;

           col = db.GetCollection(collectionName);

       }

       public string GetStringRequest(string paramter)

       {

           return HttpContext.Current.Request.QueryString[paramter] ?? "";

       }

       public int? GetIntRequest(string paramter)

       {

           string tmp = HttpContext.Current.Request.QueryString[paramter] ?? "";

           int tag = 0;

           if (!int.TryParse(tmp, out tag))

           {

               return null;

           }

           return tag;

       }

   }


复制代码


 


2.操作ElasticSearch的apicontroller如下:

复制代码


namespace Supernova.Webapi.Controllers

{

   [RoutePrefix("api")]

   public class ESTestApiController : BaseApiController

   {

        [Route("estest")]

       [HttpGet]

       public object Search()

       {

            //1 搜索数据

           string key = GetStringRequest("Key");

           int? from = GetIntRequest("from");

           int? size = GetIntRequest("size");

           

           return ElasticSearchHelper.Intance.Search<person>("db_test", "person", key ?? "方鸿渐", from == null ? 0 : from.Value, size == null ? 20 : size.Value);


           

           

       }

        [Route("estest/SearchFullFileds")]

        [HttpGet]

        public object SearchFullFileds()

        {

            //1 搜索数据

            string key = GetStringRequest("Key");

            int? from = GetIntRequest("from");

            int? size = GetIntRequest("size");            

            return ElasticSearchHelper.Intance.SearchFullFileds<person>("db_test", "person", key ?? "方鸿渐", from == null ? 0 : from.Value, size == null ? 20 : size.Value);




        }

        [Route("estest/SearchFullFiledss")]

        [HttpGet]

        public object SearchFullFiledss()

        {

            //1 搜索数据

            string key = GetStringRequest("Key");

            int? from = GetIntRequest("from");

            int? size = GetIntRequest("size");            

            return ElasticSearchHelper.Intance.SearchFullFiledss<person>("db_test", "person", key ?? "方鸿渐", from == null ? 0 : from.Value, size == null ? 20 : size.Value);




        }

       /// <summary>

        /// 索引数据

       /// </summary>

       /// <returns></returns>

        [Route("estest/index")]

        [HttpGet]

        public object index()

        {            

            int length = S.test.Length;

            Random rd = new Random();

            Random rdName = new Random();

            ParallelOptions _po = new ParallelOptions();

            _po.MaxDegreeOfParallelism = 4;

            Parallel.For(0, 10000000, _po, c =>

            {


                var start = rd.Next(0, S.test.Length - 700);

                var startName = rd.Next(0, S.test.Length - 30);

                person p = new person() { age = DateTime.Now.Millisecond, birthday = DateTime.Now, id = Guid.NewGuid().ToString(), intro = S.test.Substring(start, 629) + c, name = S.test.Substring(startName, 29) + c, sex = true };

                ElasticSearchHelper.Intance.Index("db_test", "person", Guid.NewGuid().ToString(), p);

            });

            return 1;

        }

   }

   public class S

   {

       public static  string test = @"钱钟书《围城》...";

   }

}


复制代码


 


3.索引数据的api如下:

复制代码


/// <summary>

        /// 索引数据

       /// </summary>

       /// <returns></returns>

        [Route("estest/index")]

        [HttpGet]

        public object index()

        {            

            int length = S.test.Length;

            Random rd = new Random();

            Random rdName = new Random();

            ParallelOptions _po = new ParallelOptions();

            _po.MaxDegreeOfParallelism = 4;

            Parallel.For(0, 10000000, _po, c =>

            {


                var start = rd.Next(0, S.test.Length - 700);

                var startName = rd.Next(0, S.test.Length - 30);

                person p = new person() { age = DateTime.Now.Millisecond, birthday = DateTime.Now, id = Guid.NewGuid().ToString(), intro = S.test.Substring(start, 629) + c, name = S.test.Substring(startName, 29) + c, sex = true };

                ElasticSearchHelper.Intance.Index("db_test", "person", Guid.NewGuid().ToString(), p);

            });

            return 1;

        }


复制代码


索引使用的测试数据如下:


  public class S

   {

       public static  string test = @"钱钟书《围城》...";

   }


 


4.搜索api如下:

复制代码


[Route("estest")]

       [HttpGet]

       public object Search()

       {

            //1 搜索数据

           string key = GetStringRequest("Key");

           int? from = GetIntRequest("from");

           int? size = GetIntRequest("size");

           

           return ElasticSearchHelper.Intance.Search<person>("db_test", "person", key ?? "方鸿渐", from == null ? 0 : from.Value, size == null ? 20 : size.Value);


           

           

       }

        [Route("estest/SearchFullFileds")]

        [HttpGet]

        public object SearchFullFileds()

        {

            //1 搜索数据

            string key = GetStringRequest("Key");

            int? from = GetIntRequest("from");

            int? size = GetIntRequest("size");            

            return ElasticSearchHelper.Intance.SearchFullFileds<person>("db_test", "person", key ?? "方鸿渐", from == null ? 0 : from.Value, size == null ? 20 : size.Value);




        }

        [Route("estest/SearchFullFiledss")]

        [HttpGet]

        public object SearchFullFiledss()

        {

            //1 搜索数据

            string key = GetStringRequest("Key");

            int? from = GetIntRequest("from");

            int? size = GetIntRequest("size");            

            return ElasticSearchHelper.Intance.SearchFullFiledss<person>("db_test", "person", key ?? "方鸿渐", from == null ? 0 : from.Value, size == null ? 20 : size.Value);




        }


复制代码


 


WebSite中的view视图调用webapi


说明:我是直接使用ajax(jsop格式)调用webapi,返回的数据直接用knockout绑定到table中的。


视图代码如下:

复制代码


@{

   ViewBag.Title = "ElasticSearch测试";

   Layout = null;

}

<link href="~/Content/bootstrap.css" rel="stylesheet" />

<script src="~/Scripts/jquery-2.1.3.min.js"></script>

<script src="~/Scripts/knockout-3.3.0.js"></script>

<style>

   b{

       color:red;

   }

</style>

<script>

   $(function () {

       function ViewModel() {

           self = this;

           self.getData = ko.observableArray();

           //定义加载数据方法

           self.loadData = function () {

               $.get("http://192.168.0.230/api/estest//SearchFullFiledss", { key: "@Request.QueryString["key"]", from: "@Request.QueryString["from"]", size: "@Request.QueryString["size"]" }, function (data) {

                   // alert(data.hits);

                   // alert(data.list.length);

                   $("#count").text("符合条件的数据供:" + data.hits + "  共花费了:" + data.took + "毫秒");

                 

                   $.each(data.list, function (i) {

                       var date=data.list[i].birthday;

                     

                   });

                   self.getData(data.list);

               }, "jsonp");

           };

           //调用定义方法

           self.loadData();

       }

       ko.applyBindings(new ViewModel());


   });



</script>

<div id="count"></div>


<div class="row">

   <table class="table-bordered table-condensed table-hover table-striped">

       <tbody data-bind="foreach: getData">

           <tr>

               <td data-bind="text: id" />

               <td data-bind="html: name" />

               <td data-bind="text: sex" />

               <td data-bind="text: age" />                

               <td data-bind="text: birthday" />

               <td data-bind="html: intro" />

           </tr>

       </tbody>

   </table>

</div>

<script>


</script>


复制代码


 


搜索结果测试如下(我是用"api/estest//SearchFullFiledss"这个api测试的,搜索age在1到500之间,并且字段intro 或者name 包含词组key中的所有单词。):


1.首先我们看一看测试数据总共有多少:


 


我们可以看到总共db_test中总共有两千多万条数据。


 


搜索测试1


测试条件:key=上海方鸿渐&from=0&size=100,key指搜索关键短语,0是从第0条开始区数据,100是指取一百条数据,隐藏条件是age大于1小于500


 


我们可以看到,首次搜索时,两千多万条数据大约耗时3.5秒,这里还包括取100条数据的时间,如果把数据改为20条则会更快。这里的硬件配置还只限于我的本机测试(内存8G,处理器Intel i5-4590 3.3GHZ)。


 


搜索测试2


测试条件同测试1:key=上海方鸿渐&from=0&size=100,key指搜索关键短语,0是从第0条开始区数据,100是指取一百条数据,隐藏条件是age大于1小于500


 


 


我们可以看到,搜索耗时降到了大约1.5秒。这说明同一个关键词搜索越频繁,搜索速度越快,这是因为ElasticSearch会自动将搜索的内容缓存到内存中。


 


搜索测试3


测试条件:key=香烟德国&from=0&size=20,key指搜索关键短语,0是从第0条开始区数据,20是指取一百条数据,隐藏条件是age大于1小于500


 


搜索测试4


测试条件同测试3,二次相同条件搜索:key=香烟德国&from=0&size=20,key指搜索关键短语,0是从第0条开始区数据,20是指取一百条数据,隐藏条件是age大于1小于500


 


我们可以看到,在二次搜索条件相同,搜索数据降低到20条的时候,只耗时不到0.5秒。