elasticsearch--新手入门

一.认识ElasticSearch

1.为什么要使用ElasticSearch

			虽然全文搜索领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。
			但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene的配置及使用非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
			实际项目中,我们建立一个网站或应用程序,并要添加搜索功能,令我们受打击的是:搜索工作是很难的。我们希望我们的搜索解决方案要快,我们希望有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON/XML通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够从一台开始并在需要扩容时方便地扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。

2.ElasticSearch(简称ES)

			ES即为了解决原生Lucene使用的不足,优化Lucene的调用方式,并实现了高可用的分布式集群的搜索方案,其第一个版本于2010年2月出现在GitHub上并迅速成为最受欢迎的项目之一。
			首先,ES的索引库管理支持依然是基于Apache Lucene(TM)的开源搜索引擎。
			ES也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

二.ES安装及使用说明

1.安装ES

		官方下载地址:https://www.elastic.co/downloads/elasticsearch
		运行ES bin/elasticsearch.bat
		![访问 http://localhost:9200/  看到图中信息说明ES已经启动并且正常运行]			(https://img-blog.csdnimg.cn/20200610233524529.png)

2.辅助管理工具Kibana5

		Kibana5.2.2下载地址:https://www.elastic.co/downloads/kibana
		启动Kibana5 : bin\kibana.bat
		默认访问地址:http://localhost:5601
		![	Discover:可视化查询分析器
			Visualize:统计分析图表
			Dashboard:自定义主面板(添加图表)
			Timelion:Timelion是一个kibana时间序列展示组件(暂时不用)
			Dev Tools :Console(同CURL/POSTER,操作ES代码工具,代码提示,很方便)
			Management:管理索引库(index)、已保存的搜索和可视化结果(save objects)、设置 kibana 服务器属性。]
			(https://img-blog.csdnimg.cn/20200610234459195.png)

3.ES相关概念理解

			(1)Near Realtime(NRT):近实时,两个意思,从写入数据到数据可以被搜索到有一个小延迟(大概1秒);基于es执行搜索和分析可以达到秒级
			(2)Index:索引库,包含一堆有相似结构的文档数据,比如可以有一个客户索引,商品分类索引,订单索引,索引有一个名称。一个index包含很多document,一个index就代表了一类类似的或者相同的document。比如说建立一个product index,商品索引,里面可能就存放了所有的商品数据,所有的商品document。
			(3)Type:类型,每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类,一个type下的document,都有相同的field,比如博客系统,有一个索引,可以定义用户数据type,博客数据type,评论数据type。
			(4)Document&field:文档,es中的最小数据单元,一个document可以是一条客户数据,一条商品分类数据,一条订单数据,通常用JSON数据结构表示,每个index下的type中,都可以去存储多个document。一个document里面有多个field,每个field就是一个数据字段。
			(5)Cluster:集群,包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称,默认是elasticsearch)来决定的,对于中小型应用来说,刚开始一个集群就一个节点很正常
			(6)Node:节点,集群中的一个节点,节点也有一个名称(默认是随机分配的),节点名称很重要(在执行运维管理操作的时候),默认节点会去加入一个名称为“elasticsearch”的集群,如果直接启动一堆节点,那么它们会自动组成一个elasticsearch集群,当然一个节点也可以组成一个elasticsearch集群
			(7)shard(ʃɑːrd,分片):单台机器无法存储大量数据,es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。每个shard都是一个lucene index。
			(8)replica(ˈreplɪkə,复制品):任何一个服务器随时可能故障或宕机,此时shard可能就会丢失,因此可以为每个shard创建多个replica副本。replica可以在shard故障时提供备用服务,保证数据不丢失,多个replica还可以提升搜索操作的吞吐量和性能。primary shard(建立索引时一次设置,不能修改,默认5个),replica shard(随时修改数量,默认1个),默认每个索引10个shard,5个primary shard,5个replica shard,最小的高可用配置,是2台服务器。

三.ES文档操作

1.什么是ES中的文档

		document --存放数据。在ES里面 通过index索引库 type 类型(表) 行({id:name:}) 列 id /name。ES是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在ES中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。
		_index:索引库,类似于关系型数据库里的“数据库”—它是我们存储和索引关联数据的地方。
		_type:在应用中,我们使用对象表示一些“事物”,例如一个用户、一篇博客、一个评论,或者一封邮件。可以是大写或小写,不能包含下划线或逗号。我们将使用 employee 做为类型名。
		_id:与 _index  和 _type  组合时,就可以在ELasticsearch中唯一标识一个文档。当创建一个文档,你可以自定义 _id  ,也可以让Elasticsearch帮你自动生成。
		另外还包括:
		_uid文档唯一标识(_type#_id)
		_source:文档原始数据
		_all:所有字段的连接字符串

2.文档的增删改

		创建索引文档
①使用自己的ID创建
PUT {index}/{type}/{id}
{
  "field": "value",
  ...
}
②ES内置ID创建:
POST {index}/{type}/
{
  "field": "value",
  ...
}
①②ES响应内容:
{
"_index": "itsource",
"_type": "employee",
"_id": xxxxxx,
"_version": 1, //文档版本号
"created": true //是否新增
}
		更新整个文档
post {index}/{type}/{id}
{
   Id:1,
   Name:xx
}
在响应中可以看到Elasticsearch把 _version增加
		局部更新文档
POST itsource/employee/123/_update
{
“doc”:{
	"email" : "nixianhua@itsource.cn", 
	"salary": 1000
	}
}
	这个过程如下:1. 从旧文档中检索JSON2. 修改它3. 删除旧文档4. 索引新文档

		脚本更新文档
POST itsource/emploee/123/_update
{
"script" : "ctx._source.age += 5"
}
		删除文档
DELETE {index}/{type}/{id}
		批量操作bulk
			Bulk请求体格式:
				{ action: { metadata }}\n
				{ request body }\n
				{ action: { metadata }}\n
				{ request body }\n
			每行必须以 "\n"  符号结尾,包括最后一行。这是作为每行有效的分离而做的标记。
POST _bulk
{ "delete": { "_index": "itsource", "_type": "employee", "_id": "123" }}
{ "create": { "_index": "itsource", "_type": "blog", "_id": "123" }}
{ "title": "我发布的博客" }
{ "index": { "_index": "itsource", "_type": "blog" }}
{ "title": "我的第二博客" }

3.文档的简单查询

		通过文档ID获取`GET crm/employee/1
		批量获取
			方式一
GET _mget (了解)
{
	"docs" : [
		{
		"_index" : "itsource",
		"_type" : "blog",
		"_id" : 2
		},
		{
		"_index" : "itsource",
		"_type" : "employee",
		"_id" : 1,
		"_source": "email,age"
		}
	]
}
			方式二
GET itsource/blog/_mget
{
"ids" : [ "2", "1" ]
}
		空搜索:没有指定任何的查询条件,只返回集群索引中的所有文档`GET _search码片`
		分页搜索:和SQL使用 LIMIT  关键字返回只有一页的结果一样,Elasticsearch接受 from  和 size  参数:
			size  : 每页条数,默认 10
			from  : 跳过开始的结果数,默认 0
GET _search?size=5
GET _search?size=5&from=5
GET _search?size=5&from=10
		查询字符串搜索
查询年龄为25岁的员工
GET itsource/employee/_search?q=age:25

在这里插入图片描述在这里插入图片描述

4.DSL查询与过滤

		1.什么是DSL查询
			由ES提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询,DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现
GET itsource/employee/_search?q=fullName:小张

GET itsource/employee/_search
{
"query" : {
   "match" : {
   		"fullName" : "小张"
}
}
}
		模糊匹配
GET itsource/employee/_search
{
  "query": {
        "wildcard" : { "name" : "*zs*" }
    }
}
		2.DSL查询:使用DSL查询,必须要传递query参数给ES
{
"query": {
   "match_all": {}
},
"from": 20, 
"size": 10,
"_source": ["fullName", "age", "email"],
"sort": [{"join_date": "desc"},{"age": "asc"}]
}
表示 查询所有数据,查询fullName,age和email,按照加入日期和年龄进行排序
		3.DSL过滤:DSL过滤  查询文档的方式更像是对于我的条件“有”或者“没有”,--精确查询
{
"query": {
   "bool": {(must)(should)(must not)
          "must": [
			{"match": {"description": "search" }}
			],
           "filter": {
               "term": {"tags": "lucene"}
           }
    }
},
"from": 20, 
"size": 10,
"_source": ["fullName", "age", "email"],
"sort": [{"join_date": "desc"},{"age": "asc"}]
}
		4.DSL过滤和DSL查询在性能上的区别 :
				过滤结果可以缓存并应用到后续请求;
				查询语句同时 匹配文档,计算相关性,所以更耗时,且不缓存。
				过滤语句 可有效地配合查询语句完成文档过滤。
				原则上,使用DSL查询 做模糊查询 或其他需要进行相关性评分的场景,其它全用DSL过滤。

		5.使用DSL查询与过滤
			① 全匹配(match_all)
				普通搜索(匹配所有文档):
{
	"query" : {
	"match_all" : {}
	}
}
				如果需要使用过滤条件(在所有文档中过滤,bool部分默认可不写):
GET _search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_all": {}
        }
      ],
      "filter": {
        "term": {
          "name": "zs1"
        }
      }
    }
  }
}				
			② 标准查询(match和multi_match)
				match查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。如果你使用match查询一个全文本字段,它会在真正查询之前用分析器先分析查询字符:
{
	"query": {
		"match": {
		"fullName": "Steven King"
		}
	}
}
				multi_match  查询允许你做 match查询的基础上同时搜索多个字段:
{
	"query":{
		"multi_match": {
		"query": "Steven King",
		"fields": [ "fullName", "title" ]
		}
	}
}
#fullName = ‘steven King’ or  tile = ‘steven King’
			③单词搜索与过滤(Term和Terms)
				term搜索与过滤
{
	"query": {
		"bool": {
			"must": { 
			"match_all": {} 
			}, 
			"filter": { 
				"term": { 
				"tags": "elasticsearch" 
				} 
			} 
		} 
	}
}
				Terms搜索与过滤
{
	"query": {
		"terms": {
		"tags": ["jvm", "hadoop", "lucene"],
		"minimum_match": 2
		}
	}
}
#minimum_match:至少匹配个数,默认为1
			④ 组合条件搜索与过滤(Bool):组合搜索bool可以组合多个查询条件为一个查询对象,查询条件包括must、should和must_not。
{
"query": {
	"bool": {
		"must": [{"term": {"hobby": "美女"}}],
		"should": [{"term": {"hobby": "游戏"}}, 
		 {"term": {"hobby": "运动"}} 
		],
		"must_not": [
		{"range" :{"birth_date":{"lt": "1990-06-30"}}} 
		],
		        "filter": [...],
		"minimum_should_match": 1
		}
	}
}
#Hobby=美女  and (hobby=游戏 or hobby=运动) and birth_date >= 1990-06-30
#提示: 如果 bool 查询下没有must子句,那至少应该有一个should子句。但是 如果有 must子句,那么没有 should子句也可以进行查询。
			⑤ 范围查询与过滤(range)
{
	"query":{
		"range": {
			"age": {
			"gte": 20,
			"lt": 30
			}
		}
	}
}
#上例中查询年龄大于等于20并且小于30。
#gt:>    gte:>=   lt:<  lte:<=
			⑥ 存在和缺失过滤器(exists和missing)
{
	"query": {
		"bool": {
			"must": [{
			"match_all": {}
			}],
			"filter": {
			"exists": { "field": "gps" }
			}
		}
	}
}
#exists和missing只能用于过滤结果。
			⑦ 前匹配搜索与过滤(prefix):和term查询相似,前匹配搜索不是精确匹配,而是类似于SQL中的like ‘key%’
{
	"query": {
		"prefix": {
		"fullName": "张"
		}
	}
}
#查询姓张的所有人
			⑧ 通配符搜索(wildcard):使用*代表0~N个,使用?代表1个
{
	"query": {
		"wildcard": {
		"fullName": "倪*华"
		}
	}
}

四.IK分词器

	ES的IK分词器插件源码地址:https://github.com/medcl/elasticsearch-analysis-ik
		① Maven打包IK插件
		② 解压target/releases/elasticsearch-analysis-ik-5.2.2.zip文件,并将其内容放置于ES根目录/plugins/ik
		③ 重启ES
		④ 测试分词器
POST _analyze
{
  "analyzer":"ik_smart",
  "text":"中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首"
}
	分词器类型
		ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”。
		ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合;

	文档映射Mapper:ES的文档映射(mapping)机制用于进行字段类型确认,将每个字段匹配为一种确定的数据类型。
		① 基本字段类型
			字符串:text(分词),keyword(不分词)   StringField(不分词文本),TextFiled(要分词文本);text默认为全文文本,keyword默认为非全文文本
			数字:long,integer,short,double,float
			日期:date
			逻辑:boolean

		② 复杂数据类型
			对象类型:object
			数组类型:array
			地理位置:geo_point,geo_shape

	默认映射
		查看索引类型的映射配置:GET {indexName}/_mapping/{typeName}		
		ES在没有配置Mapping的情况下新增文档,ES会尝试对字段类型进行猜测,并动态生成字段和类型的映射关系。	
			JSON type											Field type
			Boolean: true or false							"boolean"
			Whole number: 123							"long"
			Floating point: 123.45							"double"
			String, valid date:"2014-09-15"			"date"
			String: "foo bar"									"string"

	简单类型映射				
		type							类型:基本数据类型,integer,long,date,boolean,keyword,text...
		enable							是否启用:默认为true。 false:不能索引、不能搜索过滤,仅在_source中存储
		boost							权重提升倍数:用于查询时加权计算最终的得分。
		format							格式:一般用于指定日期格式,如 yyyy-MM-dd HH:mm:ss.SSS
		ignore_above					长度限制:长度大于该值的字符串将不会被索引和存储。
		ignore_malformed				转换错误忽略:true代表当格式转换错误时,忽略该值,被忽略后不会被存储和索引。
		include_in_all					是否将该字段值组合到_all中。
		null_value						默认控制替换值。如空字符串替换为”NULL”,空数字替换为-1
		store							是否存储:默认为false。true意义不大,因为_source中已有数据
		index							索引模式:analyzed (索引并分词,text默认模式), not_analyzed (索引不分词,keyword默认模式),no(不索引)
		analyzer						索引分词器:索引创建时使用的分词器,如ik_smart,ik_max_word,standard
		search_analyzer					搜索分词器:搜索该字段的值时,传入的查询内容的分词器。
		fields							多字段索引:当对该字段需要使用多种索引模式时使用。
										如:城市搜索New York  下面字段city既可以分词有可以不分词
										"city": {
										     "type": "text",
										     "analyzer": "ik_smart",
										     "fields": {
										            "raw": { 
										                "type":  "keyword"
										             }
										     }
										}
										有些类型 有时候需要分词 有时候不需要分词
										city分词
										city.raw 不分词
										那么以后搜索过滤和排序就可以使用city.raw字段名


 	针对单个类型的映射配置方式
 		查询映射类型:`GET shop/goods/_mapping`
 		修改映射类型
1)Delete shop;2)PUT shop;3)POST shop/goods/_mapping{
				"goods": {
				"properties": {
					"price": {
						"type": "integer"
			            },
					"name": {
						"type": "text",
						"analyzer": "ik_smart",
						"search_analyzer": "ik_smart"
				            }
				        }
				    }
				}
			(4)加入数据
			put shop/goods/1
			{
			  "price":88,
			  "name": "iphone8"
			}
	注意:你可以在第一次创建索引的时候指定映射的类型。此外,你也可以晚些时候为新类型添加映射(或者为已有的类型更新映射)。你可以向已有映射中增加字段,但你不能修改它。如果一个字段在映射中已经存在,这可能意味着那个字段的数据已经被索引。如果你改变了字段映射,那已经被索引的数据将错误并且不能被正确的搜索到。
	
	同时对多个类型的映射配置方式
PUT {indexName}
{
  "mappings": {
    "user": {
      "properties": {
        "id": {
          "type": "integer"
        },
        "info": {
          "type": "text",
          "analyzer": "ik_smart",
          "search_analyzer"
        }
      }
    },
    "dept": {
      "properties": {
        "id": {
          "type": "integer"
        },
        ....更多字段映射配置
      }
    }
  }
}
	对象及数组类型映射	
		① 对象的映射与索引
{
	“id” : 1,
	“girl” : {
	    “name” : “王小花”,
	    “age”  : 22
	}
}
#对应的mapping配置:
{ 
	"properties": {
          "id": {
    		"type": "long"},
          	"girl": {
			"properties":{
				"name": {"type": "keyword"},
				"age": {"type": "integer"}
			}
		}
    }
}
		② 数组与对象数组(注意:数组中元素的类型必须一致。)
{
	“id” : 1,
	“hobby” : [“王小花”,“林志玲”]
}
#对应的mapping配置是:
	{ 
		"properties": {
            "id": {"type": "long"},
            "hobby": {"type": "keyword"}
	     }
	}
	全局映射:全局映射可以通过动态模板和默认设置两种方式实现;索引下所有的类型映射配置会继承_default_的配置
PUT {indexName}
{
  "mappings": {
    "_default_": { 
      "_all": {
        "enabled": false 关闭默认映射配置
      }
    },
	"user": {
		//指定自己的自定义配置
	}, 
   "dept": { 
      "_all": {
        "enabled": true //启动默认配置
      }
	},
	....
  }
}
#默认的enabled=false 表示关闭模式的配置,如果你想用,在自己的配置里面开启配置
		动态模板:dynamic_templates
"name": {
    "type": "text",
    "fields": {
        "keyword": {
            "type": "keyword",
            "ignore_above": 256
         }
     }
}
		在实际应用场景中,一个对象的属性中,需要全文检索的字段较少,大部分字符串不需要分词,因此,需要利用全局模板覆盖自带的默认模板:
PUT _template/global_template  //创建名为global_template的模板
{
  "template":   "*",  //匹配所有索引库
  "settings": { "number_of_shards": 1 }, //匹配到的索引库只创建1个主分片
  "mappings": {
    "_default_": {
      "_all": { 
        "enabled": false //关闭所有类型的_all字段
      },
      "dynamic_templates": [
        {
          "string_as_text": { 
            "match_mapping_type": "string",//匹配类型string
            "match":   "*_text", //匹配字段名字以_text结尾 a_text
            "mapping": {
              "type": "text",//将类型为string的字段映射为text类型
              "analyzer": "ik_max_word",
              "search_analyzer": "ik_max_word",
              "fields": {
                "raw": {
                  "type":  "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        },
        {
          "string_as_keyword": { 
            "match_mapping_type": "string",//匹配类型string
            "mapping": {
              "type": "keyword"//将类型为string的字段映射为keyword类型
             }
          }
        }
      ]
    }
  }}
  #上面的意思:就是如果索引库里面字段 以_text结尾 就需要进行分词,如果不是,就不分词

五.JavaAPI

1什么是JavaAPI

		ES对Java提供一套操作索引库的工具包,即Java API。所有的ES操作都使用Client对象执行
		导包
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>5.2.2</version>
</dependency>
		测试
public class Es_Test {



   // 获取客户端
    public TransportClient getClient()throws Exception{
        Settings settings = Settings.builder()
                .put("client.transport.sniff", true)
                .put("cluster.name", "my-ealsticsearch").
                        build();
        TransportClient client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301));
       return  client;
    }
   // 增加
    @Test
    public void save()throws Exception{
        TransportClient client = getClient();
        // 请求对象
        IndexRequestBuilder indexRequestBuilder = client.prepareIndex("ehr", "emp", "1");
        // 请求数据
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("name", "kd");
        map.put("id", 1) ;
        indexRequestBuilder.setSource(map);
        // 发送给es服务端
        IndexResponse indexResponse = indexRequestBuilder.get();
        System.err.println(indexResponse);
    }


    // 改
    @Test
    public void update()throws Exception{
        TransportClient client = getClient();
        // 请求对象
        UpdateRequestBuilder updateRequestBuilder = client.prepareUpdate("ehr", "emp", "1");
        // 请求数据
        Map<String,Object>map=new HashMap<String, Object>();
        map.put("name", "kd2");
        map.put("id", 1) ;
        updateRequestBuilder.setDoc(map);
        // 发送给es服务端
        UpdateResponse updateResponse = updateRequestBuilder.get();
        System.err.println(updateResponse);
    }



     // 查询
    @Test
    public void get()throws Exception{
        TransportClient client = getClient();
        // 请求对象
        GetRequestBuilder getRequestBuilder = client.prepareGet("ehr", "emp", "1");
        // 发送给es服务端
        GetResponse getFields = getRequestBuilder.get();
        System.err.println(getFields.getSource());
    }

    // 删除
    @Test
    public void delete()throws Exception{
        TransportClient client = getClient();
        // 请求对象
        DeleteRequestBuilder deleteRequestBuilder = client.prepareDelete("ehr", "emp", "1");
        // 发送给es服务端
        DeleteResponse deleteResponse = deleteRequestBuilder.get();
        System.err.println(deleteResponse);
    }

    // 批量
    @Test
    public void bulk()throws Exception{
        TransportClient client = getClient();
        BulkRequestBuilder bulkRequest = client.prepareBulk();
        for (int i = 0; i <10 ; i++) {
            // 请求数据
            Map<String,Object>map=new HashMap<String, Object>();
            map.put("name", "iPhone");
            map.put("price", 1000*i);
            map.put("local", "cn");
            map.put("id",i) ;
            IndexRequestBuilder indexRequestBuilder = client.prepareIndex("ehr", "emp", i+"");
            indexRequestBuilder.setSource(map);
            bulkRequest.add(indexRequestBuilder);
        }
       //  批量请求
        BulkResponse bulkResponse = bulkRequest.get();
        if (bulkResponse.hasFailures()) {
//处理错误
            System.err.println("批量失败");
        }
    }

// 查询 匹配 iPhone 查出最高的价格前两条,并且过滤出# 是cn的地区 7000-9000
   @Test
   public void search()throws Exception{
        // 客户端
       TransportClient client = getClient();
       // 条件
    //   BoolQueryBuilder bool= new BoolQueryBuilder();
       BoolQueryBuilder bool= QueryBuilders.boolQuery();
       // 匹配
       bool.must(new MatchQueryBuilder("name", "iphone"));
     // 过滤条件
       List<QueryBuilder> filter = bool.filter();
       filter.add(new TermQueryBuilder("local", "cn"));
       filter.add(new RangeQueryBuilder("price").gte(7000).lte(10000));
       //  请求
       SearchResponse searchResponse =
               client.prepareSearch("ehr").setTypes("emp").setFrom(0).setSize(2)
                       .addSort("price", SortOrder.DESC)
                       .setQuery(bool)
                       .get();
       // 获取数据
       SearchHit[] hits = searchResponse.getHits().getHits();
       for (SearchHit hit : hits) {
           System.err.println(hit.getSource());
       }

   }

}

springboot集成elasticsearch

	导包
<dependencies>
     <!--springboot 对spring data es支持-->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
      </dependency>
</dependencies>
	yml配置
spring:
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 127.0.0.1:9300 
	测试
@Data
@Document(indexName = "shop",type = "GoodsEo")
public class GoodsEo {
    @Id
    private Long id;      // 编号
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String name;    // 名称 //细密度ik_max_word 粗密度 ik_smart
    @Field(type = FieldType.Keyword)
    private String country; // 国家
    @Field(type = FieldType.Double)
    private double price;   // 价格
}

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ESRunApp.class)
public class Es_Test {

    @Autowired
    ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    GoodsRepo goodsRepo;

    @Test
    public void createIndex()throws Exception{
        // 创建索引库
        elasticsearchTemplate.createIndex(GoodsEo.class);
        // 创建字段类型
        elasticsearchTemplate.putMapping(GoodsEo.class);

    }
    // 增
    @Test
    public void save()throws Exception{
        GoodsEo goodsEo=new GoodsEo();
        goodsEo.setId(1L);
        goodsEo.setName("iphone");
        goodsEo.setCountry("cn");
        goodsEo.setPrice(1100);
        goodsRepo.save(goodsEo);
    }

    // 批量同步 数据到es库
    @Test
    public void saveALL()throws Exception{
        List<GoodsEo>list=new ArrayList<>();
        for (long i = 0; i < 10; i++) {
            GoodsEo goodsEo=new GoodsEo();
            goodsEo.setId(i);
            goodsEo.setName("iphone");
            goodsEo.setCountry("cn");
            goodsEo.setPrice(1000*i);
            list.add(goodsEo);
        }
        goodsRepo.saveAll(list);
    }
    // 删除
    @Test
    public void del()throws Exception{
        goodsRepo.deleteById(1L);
    }

    // 更新
    @Test
    public void saveupdte()throws Exception{
        GoodsEo goodsEo=new GoodsEo();
        goodsEo.setId(2L);
        goodsEo.setName("iphone");
        goodsEo.setCountry("cn");
        goodsEo.setPrice(2100);
        goodsRepo.save(goodsEo);
    }

    // 查询
    @Test
    public void findAll()throws Exception{

        Iterable<GoodsEo> all = goodsRepo.findAll();
        for (GoodsEo goodsEo : all) {
            System.err.println(goodsEo);
        }
    }

    // 查询商品是iphone,国家为cn的的,价格最高的前3条的数据
    @Test
    public void query()throws Exception{
      // 构建查询对象
        NativeSearchQueryBuilder nativeSearchQueryBuilder =new NativeSearchQueryBuilder();
        // 关键字匹配  bool  must match
        BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
        boolQueryBuilder.must(new MatchQueryBuilder("name", "iphone"));
        //  过滤条件
        List<QueryBuilder> filter = boolQueryBuilder.filter();
        filter.add(new TermQueryBuilder("country","cn" ));
        //   排序
        nativeSearchQueryBuilder.withSort(new FieldSortBuilder("price").order(SortOrder.DESC));
        //  分页
        nativeSearchQueryBuilder.withPageable(PageRequest.of(0, 3));
        Page<GoodsEo> page = goodsRepo.search(nativeSearchQueryBuilder.build());
        System.err.println("总条数:"+page.getTotalElements());
        for (GoodsEo goodsEo : page) {
            System.err.println(goodsEo);
        }


    }


}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值