html
首先咱们对ES的解压目录作一个简单的了解:json
而后就是配置文件目录中的三个配置文件作一个说明:bootstrap
elasticsearch.ymlwindows
点击进去里面的配置全是被注释掉的,咱们能够加入下面的数据做为配置api
jvm.options数组
有关JVM属性的配置,通常咱们就设置堆的最小最大值,通常设为相等,不能超过物理内存的一半缓存
-Xms2g -Xmx2gapp
log4j2.propertiesjvm
日志文件的配置,ES使用log4j,配置一下日志级别就OKelasticsearch
建立索引库
put http://localhost:9200/索引库名称
number_of_shards:设置分片的数量,在集群中一般设置多个分片,表示一个索引库将拆分红多片分别存储不一样的结点,提升了ES的处理能力和高可用性,入门程序使用单机环境,这里设置为1。
number_of_replicas:设置副本的数量,设置副本是为了提升ES的高可靠性,单机环境设置为0.
建立映射
post http://localhost:9200/索引库名称/类型名称/_mapping
类型名称暂时没有意义存在,随便取一个便可,好比doc这种没有意义的
插入文档
put 或Post http://localhost:9200/索引库名称/类型名称/文档id
关于最后的文档id,咱们若是有设置就会使用咱们本身的,若不设置,ES会自动生成
搜索文档
根据文档id查询:
get http://localhost:9200/索引库名称/类型名称/文档id
查询全部文档:
get http://localhost:9200/索引库名称/类型名称/_search
根据某个属性的的值插叙:
get http://localhost:9200/索引库名称/类型名称/_search?q=name:bootstrap
根据name属性的值为bootstrap进行查询,前面固定格式
查询结果参数解析
查询结果通常会有以下数据显示
ES默认自带的分词器对于中文而言是单字分词,好比我爱祖国,ES会一个字一个字的分词,这样很明显不行
咱们查看下面的分词效果
post:localhost:9200/_analyze
{"text":"测试分词器,我爱祖国"}
ES在以前的文件目录说明哪里也有说到,ES是支持插件机制的,咱们将IK丢pligins包里就好,记得重启ES
咱们手动指定使用的分词器,查看下面的分词效果
post:localhost:9200/_analyze
{"text":"测试分词器,我爱我本身","analyzer":"ik_max_word"}
而后发现好像有点复合咱们国人的口味了,这里ik分词有两个模式
ik_max_word ,这个就是咱们上面使用到的一个模式,划分粒度比较细,通常用于存储的时候,进行分词存储索引
ik_smart ,相对而言,这个就要粗旷一些了,通常在检索索引时,对检索条件的字段进行粗旷的分词
好比:下面这句话的意思就是name属性在索引和在搜索时都是用ik_max_word模式
"name": { "type": "text", "analyzer":"ik_max_word" }
再好比:索引时使用“ik_max_word”分词,搜索时使用“ik_smart”提升搜索精确性
"name": { "type": "text", "analyzer":"ik_max_word", "search_analyzer":"ik_smart" }
有一些特殊的领域是有一些专有的词语的,而Ik是分辨不出来,因此这里须要使用到IK的自定义词库
首先定义咱们本身的词库:my.dic
记得保存为UTF-8格式,否则读取不到
而后咱们再配置文件中去加载咱们的自定义词库:IKAnalyzer.cfg.xml
而后重启ES,查看分词效果
post:localhost:9200/_analyze
{"text":"死亡野格儿","analyzer":"ik_max_word"}
查询全部索引的映射:
建立映射
post :http://localhost:9200/索引库名/类型名_mapping
映射一旦建立,已有的映射是不容许更改,只能新增或者删除重建
删除映射也只能经过删除索引来完成
核心的字段类型:
映射的类型选好了,还有一些其余的属性能够设置
analyzer :经过该属性指定分词器及模式
name属性的类型为text,在索引时使用“ik_max_word”分词器模式
在搜索时使用"ik_smart "分词器模式分词
通常都是建议在索引的时候词语最细化,在搜索时,对搜索条件粗旷化提升搜索精度
index:经过该属性指定是否索引,默认为true
只有在设置为false时,该属性的值是不会存入索引库的,也不会被检索到
好比pic属性表示的是图片的地址,通常咱们不uhi把这个地址做为搜索条件进行检索,故而设置为false
store:额外存储,通常不用理会
是否在source以外存储,每一个文档索引后会在 ES中保存一份原始文档,存放在"source"中,通常状况下不须要设置 store为true,由于在source中已经有一份原始文档了。
上面咱们说明了text类型的属性在映射时均可以is盒子分词器,keyword字段是一个关键字字段,一般搜索keyword是按照总体搜索的,是不会作分词,因此查询的时候是须要精确匹配的,好比邮政编码,身份证号等是不会且不该该作分词的,keywoed文本通常用于过滤,排序,聚合等场合
映射以下:
插入文档
根据name或者身份证号查询
Get:http://localhost:9200/索引库/类型名称/_search?q=name:狗剩儿
这样是查询不到的,由于name属性是keyword类型,必须精确匹配
日期类型也是不用设置分词器的一种类型,通常日期类型用于排序
经过format设置日期的格式,上面的这个列子容许date字段储存年月日时分秒||年月日这两种格式
插入文档以下:Post:Post :http://localhost:9200/索引库/类型名/文档id
{ "time":"2018‐08‐15 20:28:58" }
尽可能选择范围晓得类型,提升检索效率节省空间
对于浮点数,尽可能用比列因子,好比一个鸡蛋的单价是1.2元/个,咱们将别列因子设置为100,这在ES中会按照分储存,映射以下:
由于咱们将比列因子设置为100,因此储存的时候,会将1.2 * 100 进行储存
使用比列因子的好处就在与整型比浮点型更容易压缩,节约空间,固然若是比列因子不合适,咱们再选范围小的去存
pom.xml:核心依赖
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>6.2.1</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>6.2.1</version> </dependency>
Spring容器注入客户端
注意这里注入两个版本的客户端一个是高版本,推荐使用的RestHighLevelClient,但功能可能不是很完善
RestClient低版本的客户端,当咱们高版本的客户端不能使用时,考虑使用这个
@Configuration public class ElasticsearchConfig { @Value("${test.elasticsearch.hostlist}") private String hostlist; //获取高版本的客户端 @Bean public RestHighLevelClient restHighLevelClient(){ //解析hostlist配置信息 String[] split = hostlist.split(","); //建立HttpHost数组,其中存放es主机和端口的配置信息 HttpHost[] httpHostArray = new HttpHost[split.length]; for(int i=0;i<split.length;i++){ String item = split[i]; httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http"); } //建立RestHighLevelClient客户端 return new RestHighLevelClient(RestClient.builder(httpHostArray)); } //项目主要使用RestHighLevelClient,对于低级的客户端暂时不用 @Bean public RestClient restClient(){ //解析hostlist配置信息 String[] split = hostlist.split(","); //建立HttpHost数组,其中存放es主机和端口的配置信息 HttpHost[] httpHostArray = new HttpHost[split.length]; for(int i=0;i<split.length;i++){ String item = split[i]; httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http"); } return RestClient.builder(httpHostArray).build(); } }
首先注入Java客户端,咱们使用第一个便可:
//高版本的客户端
@Autowired RestHighLevelClient highClient; //低版本的客户端
@Autowired RestClient restClient; //建立索引库
@Test public void CreateIndexTest() throws IOException { //建立索引请求对象,并设置索引名称
CreateIndexRequest createIndexRequest = new CreateIndexRequest("test_index"); //设置索引参数
createIndexRequest.settings(Settings.builder().put("number_of_shards",1) .put("number_of_replicas",0)); //设置映射
createIndexRequest.mapping("doc"," {\n" +
" \t\"properties\": {\n" +
" \"name\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\":\"ik_max_word\",\n" +
" \"search_analyzer\":\"ik_smart\"\n" +
" },\n" +
" \"description\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\":\"ik_max_word\",\n" +
" \"search_analyzer\":\"ik_smart\"\n" +
" },\n" +
" \"studymodel\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"price\": {\n" +
" \"type\": \"float\"\n" +
" }\n" +
" }\n" +
"}", XContentType.JSON); //建立索引操做客户端
IndicesClient indices = highClient.indices(); //建立响应对象
CreateIndexResponse createIndexResponse = indices.create(createIndexRequest); //获得响应结果
boolean acknowledged = createIndexResponse.isAcknowledged(); System.out.println(acknowledged); }
首先咱们建立一个名为“test_index”的索引库
并建立以下索引:
插入如下数据做为测试数据:id分别为一、二、3
最基本的搜索咱们前面意思使用过了:
以这样的格式: get ../_search?q=.....
DSL:"Domain Specific Language "
是ES提出的基于json的搜索方式,在搜索时键入特定的json格式的数据来哇称搜索,所有POST请求
通常项目中都是使用的DSL搜索
@Test public void queryAllTest() throws IOException { //建立搜索请求对象,绑定索引库和类型 SearchRequest searchRequest = new SearchRequest("test_index"); searchRequest.types("doc"); //建立:搜索源构建对象 SearchSourceBuilder builder = new SearchSourceBuilder(); //指定搜索方式:matchAllQuery builder.query(QueryBuilders.matchAllQuery()); //设置源字段过滤,第一个数组表示要包含的字段,第二个数组表示不包括的字段 builder.fetchSource(new String[]{"name","studymodel"},new String[]{}); //向搜索请求中设置搜索源 searchRequest.source(builder); //使用客户端发起搜索,得到结果 SearchResponse searchResponse = highClient.search(searchRequest); //搜索结果 SearchHits hits = searchResponse.getHits(); //从搜索结果中获得 : 匹配分高位于前面的文档 SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { Map<String, Object> map = hit.getSourceAsMap(); System.out.println(map.get("name")); System.out.println(map.get("studymodel")); } }
使用注意事项:
在咱们设置源字段过滤的时候,咱们只选取了着两个字段,当咱们获取对结果后,也只能获取这两个字段的数据
Term Query为精确查询,在搜索时会总体匹配关键字,再也不将关键字分词作搜索
请求方式:根据id 1和2精确匹配数据
Java,注意事项已经在图片中给出
match Query:全文检索,先对咱们搜索的词条进行分词,而后将分好的词再拿去意义匹配查询
Term Query是不作分词,match Query是要作分词,这里作个对比,利于记忆
在这个请求中,query的值为咱们搜索的关键词,会被分词,在这个列子中会被分为“是”、“一”两个字
operator:咱们分词后出现了两个词条,只要有一个词条匹配上就命中,与之相应的还有and,表示两个或多个词条必须同时匹配上才能命中,在这里还有扩展,好比咱们搜索的关键字分词后为三个字,是一个字匹配上就命中呢?仍是两个字匹配上算命中呢?仍是所有匹配词条匹配上才能算命中呢?ES提供了占比的方式来检索数据,见下:
minimum_should_match :关键字检索分词时,匹配文档的关键字分词词条百分比指定
"是一个"这个词再被分词时,ik会把它分为四个词,分别为:"是"、"一"、"一个"、"个";
咱们设的80%,表示的意思,一共4个词条,占比8成为 4 * 80% = 3.2 取整为3,表示命中的文档必须有三个词条匹配上
扩展玩法:提高权重boost
搜索关键词是"Spring开发",在咱们检索该条数据的时候,通常但愿的的是名字为"Spring开发",而不是描述中包含这个关键字,因此咱们想提升这个关键字在搜索时,对于name字段作特殊照顾,这样就能够将name字段与Spring开发匹配上的文档得分提升,排在命中的前面
布尔查询实现将多个查询组合起来
三个参数
must:文档必须匹配must所包含的查询条件
should:文档必须匹配should所包含的条件的一个或多个
must_not:文档不能匹配must_not包含的任意一个查询条件
下面这个列子自行替换关键字进行测试
有点绕,我给圈出来了,很好看明白。
含义就很重要,须要划线要考:是针对结果进行过滤
过滤器的做用为判断该文档是否匹配,不会去计算匹配得分,性能比查询要高,缓存也方便,推荐的话:
尽可能使用过滤器是显示查询或者经过过滤器 + 查询共同检索
过滤器在布尔查询中使用:
filter:过滤,term和range一次只能对一个字段进行设置过滤条件
term:项匹配过滤,留下studymodel为201004的文档
range:范围查询,价格price>60 且 <100的文档
能够对一个字段进行设置排序,支持在keyword,date,float等类型上添加排序,text不容许排序
过滤价格在0—100区间的全部文档,优先按照studymodel降序排序,其次在根据价格升序排序
高亮显示能够将搜索结果一个或多个字突出显示,以便向用户展现匹配关键字的位置
在搜索语句中添加highlight便可实现,这个我把检索结果也贴出来方便查看
---------------------------------------------------------------------
最后由于咱们只获取了高亮里面的name:ElasticSearch<tag1>开发</tag2><tag1>学习</tag2>
由于可读性,Json我都是截图的的方式展现的,索性代码也是截图了,后续可能还有补充......
献上Es相关的资源:https://pan.baidu.com/s/10LZyR2jX2WAnEsLibHLAfA 提取码:yc90