第一节: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
(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; }
多条
/// <summary> /// 03-插入多条数据 /// </summary> /// <param name="list"></param> [HttpPost] public bool CreateList(List<Product> list) { var result = esClient.IndexMany(list, myDbName); return result.IsValid; }
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; }
删除多条
/// <summary> /// 05-删除多条数据 /// (传入的数据只要有id即可) /// </summary> /// <param name="Products"></param> [HttpPost] public bool DeleteMany(List<Product> Products) { var result = esClient.DeleteMany(Products, myDbName); return result.IsValid; }
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; }
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}"; }
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; }
根据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; }
分页查询
/// <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; }
根据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; }
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; }
文本查找
/// <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; }
排序
/// <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; } }
文本查找-多条件
/// <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; }
范围查找-根据价格
/// <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; }
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。