elasticsearch.net项目实战

Elasticsearch.net项目实战-LMLPHP

@智客幸达


目录

  • Elasticsearch+kibana
    • 环境搭建
      • windows 10环境配置
      • 安装Elasticsearch
      • head安装(非必需)
      • 安装kibana
    • DSL的基本使用
      • 增加
      • 修改
      • 查询
      • 删除
  • Elasticsearch .Net
    • Low level client基本使用
    • 项目实战
  • 总结
  • 参考

一、环境搭建
 

  1. java环境安装

     jdk下载:

     安装完成之后就是配置环境变量:

     查看是否安装成功:

2.安装Elasticsearch

     elasticsearch-5.6.11下载:

解压到C:\ELk 备用。

3.head安装(非必需)

     head下载:

解压到C:\ELk\elasticsearch-5.6.11

     node下载:

安装node

检查node和npm是否安装成功

path环境变量末尾 会自动增加 C:\Program Files\nodejs
安装 phantomjs
官网:http://phantomjs.org/下载【配置环境变量】

安装grunt
npm install -g grunt-cli

执行C:\ELk\elasticsearch-5.6.11\bin\elasticsearch.bat

执行命令启动 head

浏览器访问:http://localhost:9100/

4.安装kibana

     kibana-5.6.9-windows-x86下载:

下载之后,解压到C:\ELk\kibana-5.6.9-windows-x86

执行C:\ELk\kibana-5.6.9-windows-x86\bin\kibana.bat

浏览器访问:http://localhost:5601


二、DSL的基本使用

  • 创建文档
PUT people/person/1?op_type=create
{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elasticsearch"
}
  • 修改
POST /user/guest/20/_update
{
    "doc": {
      "RealName":"LukyHuu20"
    }
}
  • 查询
GET /user/guest/_search
{
    "query": {
      "match": {
        "Id":22
      }
    }
}
  • 删除
DELETE /user/guest/15
{

}

三、Elasticsearch .Net

     elasticsearch是以restfulAPI方式对外提供接口,并提供客户端给多种语言使用。Elasticsearch uses standard RESTful APIs and JSON. We also build and maintain clients in many languages such as Java, Python, .NET, SQL, and PHP. Plus, our community has contributed many more. They’re easy to work with, feel natural to use, and, just like Elasticsearch, don't limit what you might want to do with them.
参考(https://www.elastic.co/products/elasticsearch)

1.Low level client基本使用

     本文是介绍ES的.NET客户端,Elasticsearch .Net - Low level client[5.x]

通过引入对应的版本的客户端,便可通过C#操作ES。参考(https://www.elastic.co/guide/en/elasticsearch/client/net-api/5.x/elasticsearch-net.html)

连接

var settings = new ConnectionConfiguration(new Uri("http://example.com:9200"))
    .RequestTimeout(TimeSpan.FromMinutes(2));

var lowlevelClient = new ElasticLowLevelClient(settings);

插入文档

 var indexResponse = lowlevelClient.Index<byte[]>("user", "guest", user.Id.ToString(), user);
 byte[] responseBytes = indexResponse.Body;

更新文档

var searchResponse = lowlevelClient.Update<string>("user", "guest", id.ToString(), new
                {
                    doc = new
                    {
                        RealName = realname,
                        Description = description
                    }
                });

bool successful = searchResponse.Success;

查询

var searchResponse = lowlevelClient.Search<string>("user", "guest", new
                {
                    query = new
                    {
                        match = new
                        {
                            Id = id
                        }
                    }
                });

bool successful = searchResponse.Success;

删除

var searchResponse = lowlevelClient.Delete<string>("user", "guest", id.ToString());

                bool successful = searchResponse.Success;

2.项目实战

使用nuget安装Elasticsearch.Net 5.6.4

安装完后,

基本的增删该查在项目中的实现上面已经有所介绍,这里重点讲一下查询:

笔者使用的.NET MVC5 Web框架,对于返回的结果笔者做了一个简单封装:


public class ESearchRoot<T>
    {
        /// <summary>
        ///
        /// </summary>
        public int took { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string timed_out { get; set; }
        /// <summary>
        ///
        /// </summary>
        public _shards _shards { get; set; }
        /// <summary>
        ///
        /// </summary>
        public Hits<T> hits { get; set; }
    }

    public class _shards
    {
        /// <summary>
        ///
        /// </summary>
        public int total { get; set; }
        /// <summary>
        ///
        /// </summary>
        public int successful { get; set; }
        /// <summary>
        ///
        /// </summary>
        public int skipped { get; set; }
        /// <summary>
        ///
        /// </summary>
        public int failed { get; set; }
    }

    public class HitsItem<T>
    {
        /// <summary>
        ///
        /// </summary>
        public string _index { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string _type { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string _id { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string _score { get; set; }
        /// <summary>
        ///
        /// </summary>
        public T _source { get; set; }
        /// <summary>
        ///
        /// </summary>
        public List<int> sort { get; set; }
        /// <summary>
        ///
        /// </summary>
        public Highlight highlight { get; set; }
    }

    public class Hits<T>
    {
        /// <summary>
        ///
        /// </summary>
        public int total { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string max_score { get; set; }
        /// <summary>
        ///
        /// </summary>
        public List<HitsItem<T>> hits { get; set; }
    }

    public class Highlight
    {
        /// <summary>
        ///
        /// </summary>
        public List<string> Description { get; set; }
    }

因为soure返回的对象是不定的,所以使用了泛型。
本项目soure对应的类,user:


 ///<summary>
    ///
    /// </summary>
    public class User
    {
        /// <summary>
        ///
        /// </summary>
        public string Account { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string Phone { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string Email { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string RealName { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string CanReview { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string CanExcute { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string Avatar { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string IsUse { get; set; }
        /// <summary>
        ///
        /// </summary>
        public int Id { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        ///
        /// </summary>
        public string Description { get; set; }
        /// <summary>
        ///
        /// </summary>
        public DateTime CreateTime { get; set; }
        /// <summary>
        ///
        /// </summary>
        public DateTime ModifyTime { get; set; }
    }
    

项目使用了带条件的分页查询:

public List<AdminUser> GetBySomeWhere(string keyword, int limit, int pageSize, out int total)
        {
            List<AdminUser> users = new List<AdminUser>();

            total = 0;
            try
            {
                var settings = new ConnectionConfiguration(new Uri("http://localhost:9200/"))
   .RequestTimeout(TimeSpan.FromMinutes(2));

                var lowlevelClient = new ElasticLowLevelClient(settings);

                //根据不同的参数 来构建不同的查询条件
                var request = new object();
                if (!String.IsNullOrEmpty(keyword))
                {
                    request = new
                    {
                        from = limit,
                        size = pageSize,
                        query = new
                        {
                            match = new
                            {
                                Description = keyword
                            }
                        },
                        highlight = new
                        {
                            fields = new
                            {
                                Description = new { }
                            }
                        },
                        sort = new
                        {
                            Id = new
                            {
                                order = "desc"
                            }
                        }
                    };
                }
                else
                {
                    request = new
                    {
                        from = limit,
                        size = pageSize,
                        query = new
                        {
                            match_all = new
                            {

                            }
                        },
                        highlight = new
                        {
                            fields = new
                            {
                                Description = new { }
                            }
                        },
                        sort = new
                        {
                            Id = new
                            {
                                order = "desc"
                            }
                        }
                    };
                }


                var searchResponse = lowlevelClient.Search<string>("user", "guest", request);

                bool successful = searchResponse.Success;
                var responseJson = searchResponse.Body;

                if (!successful)
                {
                    return users;
                }

                ESearchRoot<User> root = JsonHelper.JSONStringObject<ESearchRoot<User>>(responseJson);
                if (root != null)
                {
                    total = root.hits.total;
                    foreach (HitsItem<User> item in root.hits.hits)
                    {
                        if (item._source != null)
                        {
                            string highlightDescription = String.Empty;
                            StringBuilder sbDs = new StringBuilder();
                            if (item.highlight != null && item.highlight.Description.Count > 0)
                            {
                                //ighlightDescription = item.highlight.Description[0];
                                foreach (var d in item.highlight.Description)
                                {
                                    sbDs.Append(d);
                                }
                                highlightDescription = sbDs.ToString();
                            }

                            AdminUser user = new AdminUser
                            {
                                Id = item._source.Id,
                                RealName = item._source.RealName,
                                Account = item._source.Account,
                                Email = item._source.Email,
                                Phone = item._source.Phone,
                                //IsUse=item._source.IsUse,
                                Avatar = item._source.Avatar,
                                Description = item._source.Description,
                                HighlightDescription = highlightDescription,
                                CreateTime = item._source.CreateTime,
                                ModifyTime = item._source.ModifyTime
                            };
                            users.Add(user);
                        }
                    }
                }

                return users;
            }
            catch (ElasticsearchClientException ex)
            {
                //Log4Helper.Error
            }
            return users;
        }

项目最终的效果如下:

四、总结

     elasticsearch是很强大的开源工具,在实现全文搜索上有其独到之处,也是大数据的分析方面利器,值得大家深入去研究和实践。

五、参考

     个人微信公众号:

10-06 10:16