第一节:ElasticSearch简介、基本环境搭建、基于.Net快速实操

一. ElasticSearch简介

   Elasticsearch是一个非常强大的搜索引擎。它目前被广泛地使用于各个IT公司。Elasticsearch是由Elastic公司创建并开源维护的。 同时,Elastic公司也拥有Logstash及Kibana开源项目。这个三个开源项目组合在一起,就形成了 ELK 软件栈。他们三个共同形成了一个强大的生态圈。简单地说,Logstash负责数据的采集,处理(丰富数据,数据转型等),Kibana负责数据展,分析及管理。Elasticsearch处于最核心的位置,它可以帮我们对数据进行快速地搜索及分析。

     官网地址:https://www.elastic.co/cn/

     GitHub地址: https://github.com/elastic/elasticsearch

 

 

二. 环境搭建

1.  安装jdk

   这里安装jdk11

2. 安装ElasticSearch

(这里以 7.10.1为例,在win10下安装, 最新版本下载地址:https://www.elastic.co/cn/downloads/elasticsearch)

(1). 直接解压即可,解压后的目录如下:

(2). 修改配置文件,config/elasticsearch.yml

  主要是配置ip和端口,以及允许外部请求

http.port: 9200
cluster.routing.allocation.disk.threshold_enabled: false
http.cors.enabled: true
http.cors.allow-origin: "*"

配置文件如下:

# ======================== Elasticsearch Configuration =========================
#
# NOTE: Elasticsearch comes with reasonable defaults for most settings.
#       Before you set out to tweak and tune the configuration, make sure you
#       understand what are you trying to accomplish and the consequences.
#
# The primary way of configuring a node is via this file. This template lists
# the most important settings you may want to configure for a production cluster.
#
# Please consult the documentation for further information on configuration options:
# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
#
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
#
cluster.name: my-application
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#
node.name: node-1
#
# Add custom attributes to the node:
#
#node.attr.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
#path.data: /path/to/data
#
# Path to log files:
#
#path.logs: /path/to/logs
#
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
#bootstrap.memory_lock: true
#
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: localhost
#
# Set a custom port for HTTP:
#
http.port: 9200
cluster.routing.allocation.disk.threshold_enabled: false
http.cors.enabled: true
http.cors.allow-origin: "*"

#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
#discovery.seed_hosts: ["host1", "host2"]
#
# Bootstrap the cluster using an initial set of master-eligible nodes:
#
#cluster.initial_master_nodes: ["node-1", "node-2"]
#
# For more information, consult the discovery and cluster formation module documentation.
#
# ---------------------------------- Gateway -----------------------------------
#
# Block initial recovery after a full cluster restart until N nodes are started:
#
#gateway.recover_after_nodes: 3
#
# For more information, consult the gateway module documentation.
#
# ---------------------------------- Various -----------------------------------
#
# Require explicit names when deleting indices:
#
#action.destructive_requires_name: true
View Code

(3). 运行指令【elasticsearch.bat】, 如下图,启动成功。

访问 http://localhost:9200/

PS:如何开启密码验证?

   在配置文件中,增加下面配置

#开启密码验证
xpack.security.enabled: true
xpack.license.self_generated.type: basic
xpack.security.transport.ssl.enabled: true

   然后在bin目录下运行cmd指令【elasticsearch-setup-passwords interactive】,依次给elastic, kibana, logstash_system,beats_system用户设置密码,比如设置为:ypf123456,然后重启ES。

 再次访问地址:http://localhost:9200/,需要输入用户名和密码,输入 elastic 、ypf123456,登录成功。

 

 

3.  安装Kibana

(这里以 7.10.1为例,在win10下安装  下载地址:https://www.elastic.co/cn/downloads/past-releases/logstash-7-10-0 )

(1). 直接解压即可,如下图

(2). 修改配置文件,config/kibana.yaml

 主要是配置连接ElasticSearch的地址 和 开启中文模式,其它保持默认即可

elasticsearch.hosts: ["http://localhost:9200"]
i18n.locale: "zh-CN"

(3). 运行命令进行启动 【kibana.bat】  (注意:要先把ElasticSearch启动)

(4). 访问:http://localhost:5601/app/home#/ ,如下图

4. 安装 Elasticvue

   在Edge浏览器上安装Elasticvue插件,可以查看ElasticSearch的相关情况。

 

 

5. 安装 ES-client

   在Edge浏览器上安装ES-client插件,可以查看ElasticSearch的相关情况。

 

 

 

三. 基于.Net实操

1.  准备

   Asp.Net Core WebApi 6.0

   程序集:【NEST 7.17.4】

   实体代码:

    /// <summary>
    /// 商品实体
    /// </summary>
    public class Product
    {
        public string Id { set; get; }    
        public string ProductTitle { set; get; }       //商品标题
        public string ProductDescription { set; get; }     // 图文描述
        public decimal ProductPrice { set; get; }       //价格
    }

2. 初始化连接

    private readonly ElasticClient esClient;
    //DB名称(ES中叫索引)
    private readonly string myDbName = "shopdb1";      //【只支持小写】

    /// <summary>
    /// 初始化连接
    /// </summary>
    public HomeController()
    {
        var node = new Uri("http://localhost:9200");
        //var settings = new ConnectionSettings(node).DefaultIndex(myDbName);   //不会默认创建
        var settings = new ConnectionSettings(node);
        esClient = new ElasticClient(settings);
    }

3. 增加相关

单条

 /// <summary>
    /// 02-插入单条数据
    /// </summary>
    /// <param name="Id">编号</param>
    /// <param name="ProductTitle">标题</param>
    /// <param name="ProductDescription">描述</param>
    /// <param name="ProductPrice">价格</param>
    [HttpGet]
    public bool CreateOne(string Id = "", string ProductTitle = "", string ProductDescription = "", decimal ProductPrice = 0)
    {
        if (Id == "")
        {
            Id = Guid.NewGuid().ToString("N");
        }
        var num = new Random().Next(1, 100);
        if (ProductTitle == "")
        {
            ProductTitle = "mate" + num;
        }
        if (ProductDescription == "")
        {
            ProductDescription = "mate" + num;
        }
        if (ProductPrice == 0)
        {
            ProductPrice = num;
        }

        Product p = new()
        {
            Id = Id,
            ProductTitle = ProductTitle,
            ProductDescription = ProductDescription,
            ProductPrice = ProductPrice
        };
        var result = esClient.Index(p, u => u.Index(myDbName));  //DB不存在的话创建 (这里称之为索引更贴切)
        return result.IsValid;

    }
View Code

多条

/// <summary>
    /// 03-插入多条数据
    /// </summary>
    /// <param name="list"></param>
    [HttpPost]
    public bool CreateList(List<Product> list)
    {
        var result = esClient.IndexMany(list, myDbName);
        return result.IsValid;
    }
View Code

 

4. 删除相关

根据id删除

 /// <summary>
    ///  04-根据id删除数据
    /// </summary>
    /// <param name="Id"></param>
    [HttpGet]
    public bool DeleteOne(string Id)
    {
        DeleteResponse result = esClient.Delete<Product>(Id, idx => idx.Index(myDbName));
        return result.IsValid;
    }
View Code

删除多条

 /// <summary>
    /// 05-删除多条数据
    /// (传入的数据只要有id即可)
    /// </summary>
    /// <param name="Products"></param>
    [HttpPost]
    public bool DeleteMany(List<Product> Products)
    {
        var result = esClient.DeleteMany(Products, myDbName);
        return result.IsValid;
    }
View Code

 

5. 修改相关

更新(根据id)

 /// <summary>
    /// 06-更新(根据Id)
    /// </summary>
    /// <param name="Id">编号</param>
    /// <param name="ProductTitle">标题</param>
    /// <param name="ProductDescription">描述</param>
    /// <param name="ProductPrice">价格</param>
    [HttpGet]
    public bool Update(string Id, string ProductTitle, string ProductDescription, decimal ProductPrice)
    {
        Product p = new()
        {
            Id = Id,
            ProductTitle = ProductTitle,
            ProductDescription = ProductDescription,
            ProductPrice = ProductPrice
        };
        var result = esClient.Update<Product>(Id, u => u.Index(myDbName).Doc(p));
        return result.IsValid;

    } 
View Code

 

6. 聚合相关

平均值、最大、最小、求和

 /// <summary>
    /// 16-各种聚合
    /// (求价格的平均值、求和、最小值、最大值)
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    public string GetAggregationsSearch()
    {

        //1. 平均值

        ValueAggregate result1 = esClient.Search<Product>(s => s.Index(myDbName)
                         .Aggregations(a => a.Average("ProductPrice_Average", aa => aa.Field(f => f.ProductPrice))
                        )
                     ).Aggregations.Average("ProductPrice_Average");


        //2. 求和
        ValueAggregate result2 = esClient.Search<Product>(s => s.Index(myDbName)
                      .Aggregations(a => a.Sum("ProductPrice_Sum", aa => aa.Field(f => f.ProductPrice))
                     )
                  ).Aggregations.Sum("ProductPrice_Sum");



        //3. 最大值
        ValueAggregate result3 = esClient.Search<Product>(s => s.Index(myDbName)
                      .Aggregations(a => a.Max("ProductPrice_Max", aa => aa.Field(f => f.ProductPrice))
                     )
                  ).Aggregations.Max("ProductPrice_Max");


        //4. 最小值
        ValueAggregate result4 = esClient.Search<Product>(s => s.Index(myDbName)
                      .Aggregations(a => a.Min("ProductPrice_Min", aa => aa.Field(f => f.ProductPrice))
                     )
                  ).Aggregations.Min("ProductPrice_Min");

        return $"ProductPrice_Average:{result1.Value},ProductPrice_Sum:{result2.Value},ProductPrice_Max:{result3.Value},ProductPrice_Min:{result4.Value}";


    }
View Code

 

7. 查询相关

查询所有

 /// <summary>
    /// 08-查询所有数据
    /// </summary>
    /// <returns></returns>

    [HttpPost]
    public IEnumerable<Product> GetAll()
    {
        //写法1
        //return esClient.Search<Product>(new SearchRequest(myDbName)).Documents;

        //写法2
        return esClient.Search<Product>(s => s.Index(myDbName)).Documents;
    }
View Code

根据ID判断是否存在

  /// <summary>
    /// 07-根据ID判断是否存在
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet]
    public bool IsExits(string id)
    {
        return esClient.DocumentExists<Product>(id, idx => idx.Index(myDbName)).Exists;
    }
View Code

分页查询

  /// <summary>
    /// 09-分页查询
    /// </summary>
    /// <param name="pageIndex">当前页码</param>
    /// <param name="pageSize">每页条数</param>
    /// <returns></returns>
    [HttpPost]
    public IEnumerable<Product> GetPageList(int pageIndex, int pageSize)
    {
        //写法1
        //var selector = new SearchRequest(myDbName);
        //selector.From = (pageIndex - 1) * pageSize;
        //selector.Size= pageSize;
        //return esClient.Search<Product>(selector).Documents;

        //写法2
        return esClient.Search<Product>(s => s.Index(myDbName)
                                              .From((pageIndex - 1) * pageSize)
                                              .Size(pageSize)
                                            ).Documents;
    }
View Code

根据id查询所有数据

  /// <summary>
    /// 10-根据Id查询所有数据
    /// </summary>
    /// <returns></returns>

    [HttpPost]
    public IEnumerable<Product> GetAllByIds(List<string> idList)
    {
        List<Product> pList = new List<Product>();
        var response = esClient.GetMany<Product>(idList, myDbName);
        foreach (var multiGetHit in response)
        {
            if (multiGetHit.Found)
            {
                pList.Add(multiGetHit.Source);
            }
        }
        return pList;
    }
View Code

 

8. 分词相关

分词查找

 /// <summary>
    /// 11-分词查找
    /// </summary>
    /// <param name="productTitle">产品标题</param>
    /// <returns></returns>
    [HttpGet]
    public IEnumerable<Product> GetByKeywordSearch(string productTitle)
    {
        return esClient.Search<Product>(s => s.Index(myDbName)
         .Query(q => q.Match(mq => mq.Field(f => f.ProductTitle).Query(productTitle)))
        ).Documents;
    }
View Code

文本查找

 /// <summary>
    /// 12-文本查找
    /// </summary>
    /// <param name="productTitle">产品标题</param>
    /// <returns></returns>
    [HttpGet]
    public IEnumerable<Product> GetByTextSearch(string productTitle)
    {
        return esClient.Search<Product>(s => s.Index(myDbName)
                        .Query(q => q.Term(u => u.ProductTitle, productTitle))
                ).Documents;
    }
View Code

排序

  /// <summary>
    /// 13-文本查找(含根据价格排序)
    /// </summary>
    /// <param name="productTitle">产品标题</param>
    /// <param name="isAsc">true:表示升序; false:表示降序</param>
    /// <returns></returns>
    [HttpGet]
    public IEnumerable<Product> GetByTextSortSearch(string productTitle, bool isAsc = true)
    {
        if (isAsc)
        {
            return esClient.Search<Product>(s => s.Index(myDbName)
                      .Query(q => q.Term(u => u.ProductTitle, productTitle))
                      .Sort(u => u.Ascending(s => s.ProductPrice))
              ).Documents;
        }
        else
        {
            return esClient.Search<Product>(s => s.Index(myDbName)
                    .Query(q => q.Term(u => u.ProductTitle, productTitle))
                    .Sort(u => u.Descending(s => s.ProductPrice))
            ).Documents;
        }

    }
View Code

文本查找-多条件

   /// <summary>
    /// 14-文本查找(多条件)
    /// </summary>
    /// <param name="myTitle">产品标题</param>
    /// <param name="myDescription">产品描述</param>
    /// <returns></returns>
    [HttpGet]
    public IEnumerable<Product> GetByTextManySearch(string myTitle, string myDescription)
    {
        return esClient.Search<Product>(s => s.Index(myDbName)
                        .Query(q => q.Term(u => u.ProductTitle, myTitle) &&
                                    q.Term(u => u.ProductDescription, myDescription)
                              )
                ).Documents;
    }
View Code

范围查找-根据价格

  /// <summary>
    /// 15-范围查找(根据价格)
    /// </summary>
    /// <param name="minValue">最小值</param>
    /// <param name="maxValue">最大值</param>
    /// <returns></returns>
    [HttpGet]
    public IEnumerable<Product> GetByRangeSearch(string minValue, string maxValue)
    {
        return esClient.Search<Product>(s =>
            s.Index(myDbName)
              .Query(q => q.TermRange(u => u.Field(f => f.ProductPrice).GreaterThanOrEquals(minValue).LessThan(maxValue)))
        ).Documents;
    }
View Code

 

 

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2022-08-30 15:35  Yaopengfei  阅读(581)  评论(1编辑  收藏  举报