接上:elasticsearch入门(二)

四、索引管理

4.1 搭建工程

4.1.1 ES客户端

ES提供多种不同的客户端:

1.TransportClient

ES提供的传统客户端,官方计划8.0版本删除此客户端

2.RestClient

RestClient是官方推荐使用的,它包括两种:Java Low Level REST Client和 Java High Level REST Client。
ES在6.0之后提供 Java High Level REST Client, 两种客户端官方更推荐使用 Java High Level REST Client,不过当前它还处于完善中,有些功能还没有。

本教程准备采用 Java High Level REST Client,如果它有不支持的功能,则使用Java Low Level REST Client。

添加依赖:

<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>

6.1.2 创建搜索工程

创建搜索工程(maven工程):xc-service-search,添加RestHighLevelClient依赖及junit依赖。

1.pom.xml

略主要的依赖参考上一节。

2.配置文件

application.yml

server:port: ${port:40100}
spring:application:name: xc‐search‐service
xuecheng:elasticsearch:hostlist: ${eshostlist:127.0.0.1:9200} #多个结点中间用逗号分隔

3、配置类

创建com.xuecheng.search.config包
在其下创建配置类:

package com.xuecheng.search.config;import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author Administrator* @version 1.0**/
@Configuration
public class ElasticsearchConfig {@Value("${xuecheng.elasticsearch.hostlist}")private String hostlist;@Beanpublic 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,对于低级的客户端暂时不用@Beanpublic 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();}}

4.启动类

package com.xuecheng.search;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;/*** @author Administrator* @version 1.0**/
@SpringBootApplication
@EntityScan("com.xuecheng.framework.domain.search")//扫描实体类
@ComponentScan(basePackages={"com.xuecheng.api"})//扫描接口
@ComponentScan(basePackages={"com.xuecheng.search"})//扫描本项目下的所有类
@ComponentScan(basePackages={"com.xuecheng.framework"})//扫描common下的所有类
public class SearchApplication {public static void main(String[] args) throws Exception {SpringApplication.run(SearchApplication.class, args);}}

4.2 创建索引库

4.2.1 API

创建索引:
put http://localhost:9200/索引名称

{"settings":{"index":{"number_of_shards":1,#分片的数量"number_of_replicas":0#副本数量}}
}

创建映射:
 发送:put http://localhost:9200/索引库名称/类型名称/_mapping

创建类型为xc_course的映射,共包括三个字段:name、description、studymodel
http://localhost:9200/xc_course/doc/_mapping

{"properties": {"name": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart"},"description": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart"},"studymodel": {"type": "keyword"},"price": {"type": "float"},"timestamp": {"type": "date","format": "yyyy‐MM‐dd HH:mm:ss||yyyy‐MM‐dd||epoch_millis"}}
}

4.2.2 Java Client

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestIndex {
@Autowired
RestHighLevelClient client;
@Autowired
RestClient restClient;
//创建索引库
@Test
public void testCreateIndex() throws IOException {//创建索引请求对象,并设置索引名称CreateIndexRequest createIndexRequest = new CreateIndexRequest("xc_course");//设置索引参数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 = client.indices();//创建响应对象CreateIndexResponse createIndexResponse = indices.create(createIndexRequest);//得到响应结果boolean acknowledged = createIndexResponse.isAcknowledged();System.out.println(acknowledged);
} //删除索引库
@Test
public void testDeleteIndex() throws IOException {//删除索引请求对像DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("xc_course");//删除索引DeleteIndexResponse deleteIndexResponse =client.indices().delete(deleteIndexRequest);//删除索引响应结果boolean acknowledged = deleteIndexResponse.isAcknowledged();System.out.println(acknowledged);}
}

4.3 添加文档

4.3.1 API

格式如下: PUT /{index}/{type}/{id} { "field": "value", ... }
如果不指定id,ES会自动生成

一个例子:
put http://localhost:9200/xc_course/doc/3

{"name ":"spring cloud实战 ","description": "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud 基础入门 3.实战SpringBoot 4. 注册中心eureka。 ","studymodel": "201001""price": 5.6
}

4.3.2 Java Client

//添加文档
@Test
public void testAddDoc() throws IOException {//准备json数据Map<String, Object> jsonMap = new HashMap<>();jsonMap.put("name", "spring cloud实战");jsonMap.put("description", "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud基础入门 3.实战Spring Boot 4.注册中心eureka。");jsonMap.put("studymodel", "201001");SimpleDateFormat dateFormat =new SimpleDateFormat("yyyy‐MM‐dd HH:mm:ss");jsonMap.put("timestamp", dateFormat.format(new Date()));jsonMap.put("price", 5.6f);//索引请求对象IndexRequest indexRequest = new IndexRequest("xc_course","doc");//指定索引文档内容indexRequest.source(jsonMap);//索引响应对象IndexResponse indexResponse = client.index(indexRequest)//获取响应结果DocWriteResponse.Result result = indexResponse.getResult();System.out.println(result);
}

4.4 查询文档

4.4.1 API

格式如下: GET /{index}/{type}/{id}

4.4.2 Java Client

//查询文档
@Test
public void getDoc() throws IOException {GetRequest getRequest = new GetRequest("xc_course","doc","4028e581617f945f01617f9dabc40000");GetResponse getResponse = client.get(getRequest);boolean exists = getResponse.isExists();Map<String, Object> sourceAsMap = getResponse.getSourceAsMap();System.out.println(sourceAsMap);
}

4.5 更新文档

4.5.1 Api

ES更新文档的顺序是:先检索到文档、将原来的文档标记为删除、创建新文档、删除旧文档,创建新文档就会重建索引。

通过请求Url有两种方法:
1、完全替换
Post:http://localhost:9200/xc_test/doc/3

{ "name":"spring cloud实战","description":"本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud 基础入门 3.实战SpringBoot 4.注册中心eureka。","studymodel":"201001""price":5.6
}

2、局部更新

下边的例子是只更新price字段。
post: http://localhost:9200/xc_test/doc/3/_update

{
"doc":{"price":66.6}
}

4.5.2 Java Client

使用 Client Api更新文档的方法同上边第二种局部更新方法。
可以指定文档的部分字段也可以指定完整的文档内容。

//更新文档
@Test
public void updateDoc() throws IOException {UpdateRequest updateRequest = new UpdateRequest("xc_course", "doc","4028e581617f945f01617f9dabc40000");Map<String, String> map = new HashMap<>();map.put("name", "spring cloud实战");updateRequest.doc(map);UpdateResponse update = client.update(updateRequest);RestStatus status = update.status();System.out.println(status);
}

4.6 删除文档

4.6.1 Api

根据id删除,格式如下:
DELETE /{index}/{type}/{id}

搜索匹配删除,将搜索出来的记录删除,格式如下:
POST /{index}/{type}/_delete_by_query

下边是搜索条件例子:

{"query": {"term": {"studymodel": "201001"}}
}

上边例子的搜索匹配删除会将studymodel为201001的记录全部删除。

4.6.2 Java Client

//根据id删除文档
@Test
public void testDelDoc() throws IOException {//删除文档idString id = "eqP_amQBKsGOdwJ4fHiC";//删除索引请求对象DeleteRequest deleteRequest = new DeleteRequest("xc_course","doc",id);//响应对象DeleteResponse deleteResponse = client.delete(deleteRequest);//获取响应结果DocWriteResponse.Result result = deleteResponse.getResult();System.out.println(result);
}

搜索匹配删除还没有具体的api,可以采用先搜索出文档id,根据文档id删除。

五、搜索管理

5.1 准备环境

5.1.1 创建映射

创建xc_course索引库:略

创建如下映射
post:http://localhost:9200/xc_course/doc/_mapping

{"properties": {"description": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart"},"name": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart"},"pic": {"type": "text","index": false},"price": {"type": "float"},"studymodel": {"type": "keyword"},"timestamp": {"type": "date","format": "yyyy‐MM‐dd HH:mm:ss||yyyy‐MM‐dd||epoch_millis"}}
}

5.1.2 插入原始数据

向xc_course/doc中插入以下数据:

插入三条数据:

http://localhost:9201/xc_course/doc/1

{ "name": "Bootstrap开发",
"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的精美界面效果。",
"studymodel": "201002","price": 38.6,"timestamp": "2018‐04‐25 19:11:35","pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

http://localhost:9201/xc_course/doc/2

{"name": "java编程基础","description": "java语言是世界第一编程语言,在软件开发领域使用人数最多。","studymodel": "201001","price": 68.6,"timestamp": "2018‐03‐25 19:11:35","pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

http://localhost:9201/xc_course/doc/3

{"name": "spring开发基础","description": "spring 在java领域非常流行,java程序员都在用。","studymodel": "201001","price": 88.6,"timestamp": "2018‐02‐24 19:11:35","pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

5.1.3 简单搜索

简单搜索就是通过url进行查询,以get方式请求ES。
格式:get ../_search?q=.....

q:搜索字符串。
例子:?q=name:spring 搜索name中包括spring的文档

5.2 DSL搜索

DSL(Domain Specific Language)是ES提出的基于json的搜索方式,在搜索时传入特定的json格式的数据来完成不同的搜索需求。

DSL比URI搜索方式功能强大,在项目中建议使用DSL方式来完成搜索

5.2.1 查询所有文档

查询所有索引库的文档。
发送:post http://localhost:9200/_search

查询指定索引库指定类型下的文档。(通过使用此方法)
发送:post http://localhost:9200/xc_course/doc/_search

{
"query": {
"match_all": {}
},
"_source" : ["name","studymodel"]
}

_source:source源过虑设置,指定结果中所包括的字段有哪些。

结果说明:

  • took:本次操作花费的时间,单位为毫秒。
  • timed_out:请求是否超时
  • _shards:说明本次操作共搜索了哪些分片
  • hits:搜索命中的记录
  • hits.total : 符合条件的文档总数 hits.hits :匹配度较高的前N个文档
  • hits.max_score:文档匹配得分,这里为最高分
  • _score:每个文档都有一个匹配度得分,按照降序排列。
  • _source:显示了文档的原始内容

JavaClient:

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestSearch {@AutowiredRestHighLevelClient client;@AutowiredRestClient restClient;//搜索type下的全部记录@Testpublic void testSearchAll() throws IOException {SearchRequest searchRequest = new SearchRequest("xc_course");searchRequest.types("doc");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchAllQuery());//source源字段过虑searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{});searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = client.search(searchRequest);SearchHits hits = searchResponse.getHits();SearchHit[] searchHits = hits.getHits();for (SearchHit hit : searchHits) {String index = hit.getIndex();String type = hit.getType();String id = hit.getId();float score = hit.getScore();String sourceAsString = hit.getSourceAsString();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String studymodel = (String) sourceAsMap.get("studymodel");String description = (String) sourceAsMap.get("description");System.out.println(name);System.out.println(studymodel);System.out.println(description);}}
}
...

5.2.2 分页查询

ES支持分页查询,传入两个参数:from和size。

  • form:表示起始文档的下标,从0开始。
  • size:查询的文档数量

发送:post http://localhost:9200/xc_course/doc/_search

{"from": 0,"size": 1,"query": {"match_all": {}},"_source": ["name","studymodel"]
}

JavaClient

SearchRequest searchRequest = new SearchRequest("xc_course");
searchRequest.types("xc_course");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//分页查询,设置起始下标,从0开始
searchSourceBuilder.from(0);
//每页显示个数
searchSourceBuilder.size(10);
//source源字段过虑
searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{});
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);

5.2.3 Term Query

Term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。

发送:post http://localhost:9200/xc_course/doc/_search

{"query": {"term": {"name": "spring"}},"_source": ["name","studymodel"]
}

上边的搜索会查询name包括“spring”这个词的文档。

JavaClient:

SearchRequest searchRequest = new SearchRequest("xc_course");
searchRequest.types("xc_course");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.termQuery("name","spring"));
//source源字段过虑
searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{});
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest);

5.2.4 根据id精确匹配

ES提供根据多个id值匹配的方法:
测试:
post: http://127.0.0.1:9200/xc_course/doc/_search

{"query": {"ids": {"type": "doc","values": ["3","4","100"]}}
}

JavaClient:

String[] split = new String[]{"1","2"};
List<String> idList = Arrays.asList(split);
searchSourceBuilder.query(QueryBuilders.termsQuery("_id", idList));

5.2.5 match Query

1、基本使用
match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。

match query与Term query区别是match query在搜索前先将搜索关键字分词,再拿各各词语去索引中搜索。

发送:post http://localhost:9200/xc_course/doc/_search

{"query": {"match": {"description": {"query": "spring开发","operator": "or"}}}
}
  • query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用逗号分隔也可以不用。
  • operator:or 表示 只要有一个词在文档中出现则就符合条件,and表示每个词都在文档中出现则才符合条件。

上边的搜索的执行过程是:

  1. 将“spring开发”分词,分为spring、开发两个词
  2. 再使用spring和开发两个词去匹配索引中搜索。
  3. 由于设置了operator为or,只要有一个词匹配成功则就返回该文档。

JavaClient:

//根据关键字搜索
@Test
public void testMatchQuery() throws IOException {SearchRequest searchRequest = new SearchRequest("xc_course");searchRequest.types("xc_course");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//source源字段过虑searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{});//匹配关键字searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring开    发").operator(Operator.OR));searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = client.search(searchRequest);SearchHits hits = searchResponse.getHits();SearchHit[] searchHits = hits.getHits();for (SearchHit hit : searchHits) {String index = hit.getIndex();String type = hit.getType();String id = hit.getId();float score = hit.getScore();String sourceAsString = hit.getSourceAsString();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String studymodel = (String) sourceAsMap.get("studymodel");String description = (String) sourceAsMap.get("description");System.out.println(name);System.out.println(studymodel);System.out.println(description);}
}

2、minimum_should_match
上边使用的operator = or表示只要有一个词匹配上就得分,如果实现三个词至少有两个词匹配如何实现?

使用minimum_should_match可以指定文档匹配词的占比:
比如搜索语句如下:

{"query": {"match": {"description": {"query": "spring开发框架","minimum_should_match": "80%"}}}
}

“spring开发框架”会被分为三个词:spring、开发、框架

设置"minimum_should_match": "80%"表示,三个词在文档的匹配占比为80%,即3*0.8=2.4,向上取整得2,表示至少有两个词在文档中要匹配成功。

对应的RestClient如下:

//匹配关键字
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("description", "前台页面开发框架 架构")
.minimumShouldMatch("80%");//设置匹配占比
searchSourceBuilder.query(matchQueryBuilder);

5.2.6 multi Query

上边学习的termQuery和matchQuery一次只能匹配一个Field,本节学习multiQuery,一次可以匹配多个字段。

1、基本使用
单项匹配是在一个field中去匹配,多项匹配是拿关键字去多个Field中匹配。

例子:
发送:post http://localhost:9200/xc_course/doc/_search
拿关键字 “spring css”去匹配name 和description字段

2、提升boost

匹配多个字段时可以提升字段的boost(权重)来提高得分

例子:
提升boost之前,执行下边的查询:
“name^10” 表示权重提升10倍,执行上边的查询,发现name中包括spring关键字的文档排在前边。

JavaClient:

MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架",
"name", "description")
.minimumShouldMatch("50%");
multiMatchQueryBuilder.field("name",10);//提升boost

5.2.7 布尔查询

布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来。
三个参数:
must:文档必须匹配must所包括的查询条件,相当于 “AND” should:文档应该匹配should所包括的查询条件其中的一个或多个,相当于 "OR" must_not:文档不能匹配must_not所包括的该查询条件,相当于“NOT”分别使用must、should、must_not测试下边的查询:

发送:POST http://localhost:9200/xc_course/doc/_search

{"_source": ["name","studymodel","description"],"from": 0,"size": 1,"query": {"bool": {"must": [{"multi_match": {"query": "spring框架","minimum_should_match": "50%","fields": ["name^10","description"]}},{"term": {"studymodel": "201001"}}]}}
}
  • must:表示必须,多个查询条件必须都满足。(通常使用must)
  • should:表示或者,多个查询条件只要有一个满足即可。
  • must_not:表示非

JavaClient:

//BoolQuery,将搜索关键字分词,拿分词去索引库搜索
@Test
public void testBoolQuery() throws IOException {//创建搜索请求对象SearchRequest searchRequest= new SearchRequest("xc_course");searchRequest.types("doc");//创建搜索源配置对象SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.fetchSource(new String[]{"name","pic","studymodel"},new String[]{});//multiQueryString keyword = "spring开发框架";MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架","name", "description").minimumShouldMatch("50%");multiMatchQueryBuilder.field("name",10);//TermQueryTermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");//布尔查询BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();boolQueryBuilder.must(multiMatchQueryBuilder);boolQueryBuilder.must(termQueryBuilder);//设置布尔查询对象searchSourceBuilder.query(boolQueryBuilder);searchRequest.source(searchSourceBuilder);//设置搜索源配置SearchResponse searchResponse = client.search(searchRequest);SearchHits hits = searchResponse.getHits();SearchHit[] searchHits = hits.getHits();for(SearchHit hit:searchHits){Map<String, Object> sourceAsMap = hit.getSourceAsMap();System.out.println(sourceAsMap);}
}

5.2.8 过虑器

过虑是针对搜索的结果进行过虑,过虑器主要判断的是文档是否匹配,不去计算和判断文档的匹配度得分,所以过虑器性能比查询要高,且方便缓存,推荐尽量使用过虑器去实现查询或者过虑器和查询共同使用。

过虑器在布尔查询中使用,下边是在搜索结果的基础上进行过虑:

{"_source": ["name","studymodel","description","price"],"query": {"bool": {"must": [{"multi_match": {"query": "spring框架","minimum_should_match": "50%","fields": ["name^10","description"]}}],"filter": [{"term": {"studymodel": "201001"}},{"range": {"price": {"gte": 60,"lte": 100}}}]}}
}
  • range:范围过虑,保留大于等于60 并且小于等于100的记录。
  • term:项匹配过虑,保留studymodel等于"201001"的记录。

注意:range和term一次只能对一个Field设置范围过虑。

JavaClient

//布尔查询使用过虑器
@Test
public void testFilter() throws IOException {SearchRequest searchRequest = new SearchRequest("xc_course");searchRequest.types("doc");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//source源字段过虑searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","description"},new String[]{});searchRequest.source(searchSourceBuilder);//匹配关键字MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架", "name", "description");//设置匹配占比multiMatchQueryBuilder.minimumShouldMatch("50%");//提升另个字段的Boost值multiMatchQueryBuilder.field("name",10);searchSourceBuilder.query(multiMatchQueryBuilder);//布尔查询BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();boolQueryBuilder.must(searchSourceBuilder.query());//过虑boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001"));boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(60).lte(100));SearchResponse searchResponse = client.search(searchRequest);SearchHits hits = searchResponse.getHits();SearchHit[] searchHits = hits.getHits();for (SearchHit hit : searchHits) {String index = hit.getIndex();String type = hit.getType();String id = hit.getId();float score = hit.getScore();String sourceAsString = hit.getSourceAsString();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String studymodel = (String) sourceAsMap.get("studymodel");String description = (String) sourceAsMap.get("description");System.out.println(name);System.out.println(studymodel);System.out.println(description);}
}

5.2.9 排序

可以在字段上添加一个或多个排序,支持在keyword、date、float等类型上添加,text类型的字段上不允许添加排序。

发送 POST http://localhost:9200/xc_course/doc/_search
过虑0--10元价格范围的文档,并且对结果进行排序,先按studymodel降序,再按价格升序

JavaClient:

@Test
public void testSort() throws IOException {SearchRequest searchRequest = new SearchRequest("xc_course");searchRequest.types("doc");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//source源字段过虑searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","description"},new String[]{});searchRequest.source(searchSourceBuilder);//布尔查询BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//过虑boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));//排序searchSourceBuilder.sort(new FieldSortBuilder("studymodel").order(SortOrder.DESC));searchSourceBuilder.sort(new FieldSortBuilder("price").order(SortOrder.ASC));SearchResponse searchResponse = client.search(searchRequest);SearchHits hits = searchResponse.getHits();SearchHit[] searchHits = hits.getHits();for (SearchHit hit : searchHits) {String index = hit.getIndex();String type = hit.getType();String id = hit.getId();float score = hit.getScore();String sourceAsString = hit.getSourceAsString();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String studymodel = (String) sourceAsMap.get("studymodel");String description = (String) sourceAsMap.get("description");System.out.println(name);System.out.println(studymodel);System.out.println(description);}
}

5.3.10 高亮显示

高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。

在搜索语句中添加highlight即可实现,如下:
Post: http://127.0.0.1:9200/xc_course/doc/_search

{"_source": ["name","studymodel","description","price"],"query": {"bool": {"must": [{"multi_match": {"query": "开发框架","minimum_should_match": "50%","fields": ["name^10","description"],"type": "best_fields"}}],"filter": [{"range": {"price": {"gte": 0,"lte": 100}}}]}},"sort": [{"price": "asc"}],"highlight": {"pre_tags": ["<tag1>"],"post_tags": ["</tag2>"],"fields": {"name": {},"description": {}}}
}

JavaClient代码如下:

@Test
public void testHighlight() throws IOException {SearchRequest searchRequest = new SearchRequest("xc_course");searchRequest.types("doc");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//source源字段过虑searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","description"},new String[]{});searchRequest.source(searchSourceBuilder);//匹配关键字MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("开发","name", "description");searchSourceBuilder.query(multiMatchQueryBuilder);//布尔查询BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();boolQueryBuilder.must(searchSourceBuilder.query());//过虑boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));//排序searchSourceBuilder.sort(new FieldSortBuilder("studymodel").order(SortOrder.DESC));searchSourceBuilder.sort(new FieldSortBuilder("price").order(SortOrder.ASC));//高亮设置HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.preTags("<tag>");//设置前缀highlightBuilder.postTags("</tag>");//设置后缀// 设置高亮字段highlightBuilder.fields().add(new HighlightBuilder.Field("name"));// highlightBuilder.fields().add(new HighlightBuilder.Field("description"));searchSourceBuilder.highlighter(highlightBuilder);SearchResponse searchResponse = client.search(searchRequest);SearchHits hits = searchResponse.getHits();SearchHit[] searchHits = hits.getHits();for (SearchHit hit : searchHits) {Map<String, Object> sourceAsMap = hit.getSourceAsMap();//名称String name = (String) sourceAsMap.get("name");//取出高亮字段内容Map<String, HighlightField> highlightFields = hit.getHighlightFields();if(highlightFields!=null){HighlightField nameField = highlightFields.get("name");if(nameField!=null){Text[] fragments = nameField.getFragments();StringBuffer stringBuffer = new StringBuffer();for (Text str : fragments) {stringBuffer.append(str.string());}name = stringBuffer.toString();}}String index = hit.getIndex();String type = hit.getType();String id = hit.getId();float score = hit.getScore();String sourceAsString = hit.getSourceAsString();String studymodel = (String) sourceAsMap.get("studymodel");String description = (String) sourceAsMap.get("description");System.out.println(name);System.out.println(studymodel);System.out.println(description);}
}

六、集群管理

6.1 集群结构

ES通常以集群方式工作,这样做不仅能够提高 ES的搜索能力还可以处理大数据搜索的能力,同时也增加了系统的容错能力及高可用,ES可以实现PB级数据的搜索。

下图是ES集群结构的示意图:

从上图总结以下概念:

  1. 结点:
    ES集群由多个服务器组成,每个服务器即为一个Node结点(该服务只部署了一个ES进程)。
  2. 分片:
    当我们的文档量很大时,由于内存和硬盘的限制,同时也为了提高ES的处理能力、容错能力及高可用能力,我们将索引分成若干分片,每个分片可以放在不同的服务器,这样就实现了多个服务器共同对外提供索引及搜索服务。
    一个搜索请求过来,会分别从各各分片去查询,最后将查询到的数据合并返回给用户。
  3. 副本:
    为了提高ES的高可用同时也为了提高搜索的吞吐量,我们将分片复制一份或多份存储在其它的服务器,这样即使当前的服务器挂掉了,拥有副本的服务器照常可以提供服务。
  4. 主结点:
    一个集群中会有一个或多个主结点,主结点的作用是集群管理,比如增加节点,移除节点等,主结点挂掉后ES会重新选一个主结点。
  5. 结点转发:
    每个结点都知道其它结点的信息,我们可以对任意一个结点发起请求,接收请求的结点会转发给其它结点查询数据。

6.2 搭建集群

下边的例子实现创建一个2结点的集群,并且索引的分片我们设置2片,每片一个副本。

6.2.1 结点的三个角色

  1. 主结点:master节点主要用于集群的管理及索引 比如新增结点、分片分配、索引的新增和删除等。
  2. 数据结点:data 节点上保存了数据分片,它负责索引和搜索操作。
  3. 客户端结点:client 节点仅作为请求客户端存在,client的
    作用也作为负载均衡器,client 节点不存数据,只是将请求均衡转发到其它结点。

通过下边两项参数来配置结点的功能:

  • node.master: #是否允许为主结点
  • node.data: #允许存储数据作为数据结点
  • node.ingest: #是否允许成为协调节点,

四种组合方式:

  • master=true,data=true:即是主结点又是数据结点
  • master=false,data=true:仅是数据结点
  • master=true,data=false:仅是主结点,不存储数据
  • master=false,data=false:即不是主结点也不是数据结点,此时可设置ingest为true表示它是一个客户端。

6.2.2创建结点 1

解压elasticsearch-6.2.1.zip 到 F:\devenv\elasticsearch\es-cloud-1\elasticsearch-6.2.1
结点1对外服务的http端口是:9200
集群管理端口是9300
配置elasticsearch.yml
结点名:xc_node_1
elasticsearch.yml内容如下:

cluster.name: xuecheng
node.name: xc_node_1
network.host: 0.0.0.0
http.port: 9200
transport.tcp.port: 9300
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["0.0.0.0:9300", "0.0.0.0:9301"]
discovery.zen.minimum_master_nodes: 1
node.ingest: true
node.max_local_storage_nodes: 2
path.data: D:\ElasticSearch\elasticsearch‐6.2.1‐1\data
path.logs: D:\ElasticSearch\elasticsearch‐6.2.1‐1\logs
http.cors.enabled: true
http.cors.allow‐origin: /.*/

启动结点1

6.2.3创建结点 2

解压elasticsearch-6.2.1.zip 到 F:\devenv\elasticsearch\es-cloud-2\elasticsearch-6.2.1
结点1对外服务的http端口是:9201
集群管理端口是9302
结点名:xc_node_2
elasticsearch.yml内容如下:

cluster.name: xuecheng
node.name: xc_node_2
network.host: 0.0.0.0
http.port: 9201
transport.tcp.port: 9301
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["0.0.0.0:9300", "0.0.0.0:9301"]
discovery.zen.minimum_master_nodes: 1
node.ingest: true
node.max_local_storage_nodes: 2
path.data: D:\ElasticSearch\elasticsearch‐6.2.1‐2\data
path.logs: D:\ElasticSearch\elasticsearch‐6.2.1‐2\logs
http.cors.enabled: true
http.cors.allow‐origin: /.*/

启动结点2

6.2.4 创建索引库

1)使用head连上其中一个结点

上图表示两个结点已经创建成功。

2)下边创建索引库,共2个分片,每个分片一个副本

 创建成功,刷新head:

上图可以看到共有4个分片,其中两个分片是副本。

3)每个结点安装IK分词器

6.2.5 集群的健康

通过访问 GET /_cluster/health 来查看Elasticsearch 的集群健康情况。

用三种颜色来展示健康状态: green 、 yellow 或者 red :

  • green:所有的主分片和副本分片都正常运行。
  • yellow:所有的主分片都正常运行,但有些副本分片运行不正常。
  • red:存在主分片运行不正常。

Get请求:http://localhost:9200/_cluster/health
响应结果:

{
"cluster_name": "xuecheng",
"status": "green",
"timed_out": false,
"number_of_nodes": 2,
"number_of_data_nodes": 2,
"active_primary_shards": 2,
"active_shards": 4,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 100
}

6.3 测试

1)创建映射并写入文档
连接 其中任意一台结点,创建映射写入文档。

Post http://localhost:9200/xc_course/doc/3

{
"name": "spring开发基础",
"description": "spring 在java领域非常流行,java软件开发人员都在用。",
"studymodel": "201001",
"price":66.6
}

响应结果:

{
"_index": "xc_course",
"_type": "doc",
"_id": "3",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}

从上边的提示可看出,两个分片都保存成功。

2)搜索
向其它一个结点发起搜索请求,查询全部数据。
3)关闭一个结点
ES会重新选中一个主结点(前提在配置结点时允许它可以为主结点)

 此时向活的结点发起搜索请求,仍然正常。

4)添加一个结点
添加结点3,端口设置为:
http端口是:9202
集群管理端口是9302
结点名:xc_node_3
此结点的配置:
node.master: false node.data: true
启动结点3,刷新head,下图显示ES将分片分在了3个结点。

向结点3发起搜索请求:
Get: http://127.0.0.1:9202/xc_course/doc/_search

全部数据可被正常搜索到。

七、SpringBoot整合Spring Data Elasticsearch

Elasticsearch提供的Java客户端有一些不太方便的地方:

  • 很多地方需要拼接Json字符串,在java中拼接字符串有多恐怖你应该懂的
  • 需要自己把对象序列化为json存储
  • 查询到结果也需要自己反序列化为对象

所以我们限制学习Spring提供的套件:Spring Data Elasticsearch 。

7.1 简介

Spring Data Elasticsearch是Spring Data项目下的一个子模块。

查看 Spring Data的官网:Redirecting…http://projects.spring.io/spring-data/

 Spring Data 是的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如MySQL),还是非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提高开发效率。

包含很多不同数据操作的模块:

Spring Data Elasticsearch的页面:Redirecting…https://projects.spring.io/spring-data-elasticsearch/

特征:

  • 支持Spring的基于@Configuration的java配置方式,或者XML配置方式
  • 提供了用于操作ES的便捷工具类ElasticsearchTemplate。包括实现文档到POJO之间的自动智能映射。
  • 利用Spring的数据转换服务实现的功能丰富的对象映射
  • 基于注解的元数据映射方式,而且可扩展以支持更多不同的数据格式
  • 根据持久层接口自动生成对应实现方法,无需人工编写基本操作代码(类似mybatis,根据接口自动得到实现)。当然,也支持人工定制查询

7.2 创建Demo工程

我们新建一个demo,学习Elasticsearch

pom依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId><version>2.1.0.RELEASE</version></dependency>

application.yml文件配置:

spring:data:elasticsearch:cluster-name: my-elasticsearchcluster-nodes: 127.0.0.1:9301,127.0.0.1:9302,127.0.0.1:9303

7.3.索引操作

7.3.1.创建索引和映射

SpringBoot-data-elasticsearch提供了面向对象的方式操作elasticsearch。

业务:将课程的信息存入elasticsearch,并且执行搜索操作。

创建一个商品对象:属性信息如下

@Data
@Document(indexName = "xc_course",type = "doc")
public class EsXcCourse {@Id@Field(type= FieldType.Keyword,store = true)private String id;@Field(type = FieldType.Text,store = true,analyzer = "standard")private String description;@Field(type = FieldType.Text,store = true,analyzer ="ik_max_word",searchAnalyzer = "ik_smart")private String name;@Field(type = FieldType.Text,index = false)private String pic;@Field(type = FieldType.Float)private Float price;@Field(type = FieldType.Keyword)private String studymodel;@Field(type = FieldType.Date,format = DateFormat.basic_date_time)private Date timestamp;
}

映射—注解:

Spring Data通过注解来声明字段的映射属性,有下面的三个注解:

  • @Document 作用在类,标记实体类为文档对象,一般有两个属性
            indexName:对应索引库名称
            type:对应在索引库中的类型
            shards:分片数量,默认5
            replicas:副本数量,默认1
  • @Id 作用在成员变量,标记一个字段作为id主键
  • @Field 作用在成员变量,标记为文档的字段,并指定字段映射属性:
    type:字段类型,是枚举:FieldType,可以是text、long、short、date、integer、object等text:存储数据时候,会自动分词,并生成索引
    keyword:存储数据时候,不会分词建立索引
    Numerical:数值类型,分两类:基本数据类型:long、interger、short、byte、double、float、half_float。浮点数的高精度类型:scaled_float需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
  • Date:日期类型
    elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
  • index:是否索引,布尔类型,默认是true
  • store:是否存储,布尔类型,默认是false
  • analyzer:分词器名称,这里的ik_max_word即使用ik分词器

创建索引:

ElasticsearchTemplate中提供了创建索引的API:

映射:

映射相关的API:

我们这里采用类的字节码信息创建索引并映射:

@Testpublic void createIndex(){// 创建索引,会根据Item类的@Document注解信息来创建boolean createFlag = elasticsearchTemplate.createIndex(EsXcCourse.class);System.out.println("####:"+createFlag);// 配置映射,会根据Item类中的id、Field等字段来自动完成映射elasticsearchTemplate.putMapping(EsXcCourse.class);}

7.3.2.删除索引

删除索引的API:

可以根据类名或索引名删除。

示例:

@Test
public void deleteIndex() {esTemplate.deleteIndex(Item.class);// 根据索引名字删除//esTemplate.deleteIndex("item1");
}

7.4 新增文档数据

7.4.1 Repository接口

Spring Data 的强大之处,就在于你不用写任何DAO处理,自动根据方法名或类的信息进行CRUD操作。只要你定义一个接口,然后继承Repository提供的一些子接口,就能具备各种基本的CRUD功能

来看下Repository的继承关系:

我们看到有一个ElasticsearchCrudRepository接口:

所以,我们只需要定义接口,然后继承它就OK了。

public interface ESGlobalSearchMapper  extends ElasticsearchRepository<ESGlobalSearch,String> {/*** 根据标题检索* @param title* @param roughTitle* @return*/List<ESGlobalSearch> findByTitleOrRoughTitle(String title, String roughTitle);
}

接下来,我们测试新增数据:

7.4.1 新增一个对象

ElasticsearchRepository#save

@Testpublic void saveTest(){ESGlobalSearch esGlobalSearch = new ESGlobalSearch();esGlobalSearch.setApplicationInfo("1");esGlobalSearch.setApplicationType(1);esGlobalSearch.setContent("测试Content");esGlobalSearch.setId("1");esGlobalSearch.setLabel("测试Label");esGlobalSearch.setRoughTitle("测试");esGlobalSearch.setTitle("测试title");ESGlobalSearch save = esGlobalSearchMapper.save(new ESGlobalSearch());}

7.4.2 批量新增

ElasticsearchRepository.saveAll(List list)

7.4.3 修改

elasticsearch中本没有修改,它是先删除再新增

修改和新增是同一个接口,区分的依据就是id。

7.5.查询

ElasticsearchRepository提供了一些基本的查询方法:

7.5.1.基本查询

ElasticsearchRepository提供了一些基本的查询方法:

我们来试试查询所有:

@Testpublic void findAllTest(){Iterable<ESGlobalSearch> iter = esGlobalSearchMapper.findAll();for (ESGlobalSearch esGlobalSearch : iter) {System.out.println(esGlobalSearch);}}

7.5.2.自定义查询

  • matchQuery:词条匹配,先分词然后在调用termQuery进行匹配

  • TermQuery:词条匹配,不分词

  • wildcardQuery:通配符匹配

  • fuzzyQuery:模糊匹配

  • rangeQuery:范围匹配

  • booleanQuery:布尔查询

7.5.2.1 match query: 

/*** 基本查询*/@Testpublic void testQuery(){// 词条查询MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "周国岭");//执行查询Iterable<ESGlobalSearch> items = this.esGlobalSearchMapper.search(queryBuilder);items.forEach(item -> System.out.println(item));}
  • NativeSearchQueryBuilder:Spring提供的一个查询条件构建器,帮助构建json格式的请求体
  • QueryBuilders.matchQuery(“title”, “小米手机”):利用QueryBuilders来生成一个查询。QueryBuilders提供了大量的静态方法,用于生成各种不同类型的查询:

Page:默认是分页查询,因此返回的是一个分页的结果对象,包含属性:

  • totalElements:总条数
  • totalPages:总页数
  • Iterator:迭代器,本身实现了Iterator接口,因此可直接迭代得到当前页的数据

7.5.2.2 分页查询 :

/*** es分页处理*/@Testpublic void testNativeQuery2(){// 构建查询条件NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();// 添加基本的分词查询queryBuilder.withQuery(QueryBuilders.termQuery("title", "杭州"));queryBuilder.withQuery(QueryBuilders.matchAllQuery());// 初始化分页参数int page = 0;int size = 3;// 设置分页参数queryBuilder.withPageable(PageRequest.of(page, size));// 执行搜索,获取结果Page<ESGlobalSearch> pages = this.esGlobalSearchMapper.search(queryBuilder.build());// 打印总条数System.out.println(pages.getTotalElements());// 打印总页数System.out.println(pages.getTotalPages());// 每页大小System.out.println(pages.getSize());// 当前页System.out.println(pages.getNumber());List<ESGlobalSearch> list = pages.getContent();list.forEach( esGlobalSearch -> System.out.println(esGlobalSearch));}

7.5.2.3 termQuery

代码略。

7.5.2.4 fuzzyQuery

@Testpublic void testFuzzyQuery(){NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();queryBuilder.withQuery(QueryBuilders.fuzzyQuery("title","杭州"));Page<ESGlobalSearch> page = this.esGlobalSearchMapper.search(queryBuilder.build());List<ESGlobalSearch> list = page.getContent();list.forEach(esGlobalSearch -> System.out.println(esGlobalSearch));}

7.5.2.5 booleanQuery

BooleanQuery(组合查询)

注意点:

BooleanClause用于表示布尔查询子句关系的类,包括:BooleanClause.Occur.MUST,BooleanClause.Occur.MUST_NOT,BooleanClause.Occur.SHOULD。必须包含,不能包含,可以包含三种.有以下6种组合:

  1. MUST和MUST:交集。
  2. MUST和MUST_NOT:表示查询结果中不能包含MUST_NOT所对应得查询子句的检索结果。
  3. SHOULD与MUST_NOT:连用时,功能同MUST和MUST_NOT。
  4. SHOULD与MUST连用时,结果为MUST子句的检索结果,但是SHOULD可影响排序。
  5. SHOULD与SHOULD:并集。
  6. MUST_NOT和MUST_NOT:无意义,检索无结果。
@Testpublic void testBooleanQuery() {NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();builder.withQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("title", "周国岭")).must(QueryBuilders.termQuery("roughTitle", "儿童周国岭科")));Page<ESGlobalSearch> list = this.esGlobalSearchMapper.search(builder.build());for (ESGlobalSearch item : list) {System.out.println(item);}}

7.5.2.6 RangeQuery

范围查找:我们的ESGlobalSearch中没有关于金额以及数目等等字段,所以我们用别的对象代替

@Test
public void testRangeQuery(){NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();//        queryBuilder.withQuery(QueryBuilders.fuzzyQuery("title","小目"));queryBuilder.withQuery(QueryBuilders.rangeQuery("price").from(3000).to(4000));Page<Item> page = itemRespository.search(queryBuilder.build());for(Item i:page){System.out.println(i);}}

7.5.2.7

elasticsearch入门(三)相关推荐

  1. 和我一起打造个简单搜索之ElasticSearch入门

    本文简单介绍了使用 Rest 接口,对 es 进行操作,更深入的学习,可以参考文末部分. 环境 本文以及后续 es 系列文章都基于 5.5.3 这个版本的 elasticsearch ,这个版本比较稳 ...

  2. ElasticSearch入门 第一篇:Windows下安装ElasticSearch

    这是ElasticSearch 2.4 版本系列的第一篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  3. ElasticSearch入门 :Windows下安装ElasticSearch

    这是ElasticSearch 2.4 版本系列的第一篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  4. ElasticSearch入门 附.Net Core例子

    1.什么是ElasticSearch? Elasticsearch是基于Lucene的搜索引擎.它提供了一个分布式,支持多租户的全文搜索引擎,它具有HTTP Web界面和无模式JSON文档. Elas ...

  5. ElasticSearch入门 第五篇:使用C#查询文档

    网址:http://www.cnblogs.com/ljhdo/p/4550135.html 这是ElasticSearch 2.4 版本系列的第五篇: ElasticSearch入门 第一篇:Win ...

  6. Elasticsearch(三)——Es搜索(简单使用、全文查询、复合查询)、地理位置查询、特殊查询、聚合操作、桶聚合、管道聚合

    Elasticsearch(三)--Es搜索(简单使用.全文查询.复合查询).地理位置查询.特殊查询.聚合操作.桶聚合.管道聚合 一.Es搜索 这里的 Es 数据博主自己上网找的,为了练习 Es 搜索 ...

  7. ElasticSearch入门-搜索如此简单

    2019独角兽企业重金招聘Python工程师标准>>> 转载:http://donlianli.iteye.com/blog/1904064 搜索引擎我也不是很熟悉,但是数据库还是比 ...

  8. Elasticsearch入门进阶篇

    文章目录 一:Elasticsearch前言 1.1:什么是搜索? 1.2:如果用数据库做搜索会怎么样? 1.3:什么是全文搜索和Lucene? 1.3.1:全文检索 1.3.2:Lucene 1.4 ...

  9. ElasticSearch入门 第二篇:集群配置

    这是ElasticSearch 2.4 版本系列的第二篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  10. Elasticsearch入门使用

    Elasticsearch入门使用 1.安装 免安装,解压后直接运行 bin 目录下的 elasticsearch.bat 文件. 启动后打开浏览器输入 localhost:9200,显示如下消息即启 ...

最新文章

  1. mysql系统变量_MySQL 系统变量(system variables)
  2. LeetCode--160--相交链表
  3. JSP-Servlet中文乱码
  4. JS的for循环小例子
  5. ReportViewer教程(5)-将数据源字段放入报表
  6. webstorm的debug模式
  7. mysql 存储过程游标 循环输出select 查询结果
  8. Qt 学习之路 2(1):序 笔记
  9. 芒果移动广告优化平台
  10. php融云开源sdk使用im,开源项目索引
  11. 自制homekit开关
  12. 21.运行Consent Page
  13. DNS 解析器(DNS Resolver)
  14. 产品化机器学习的一些思考
  15. iOS-利用粒子发射器(CAEmitterLayer) 制作发射动画
  16. (深度神经网络多.py文件)python打包过程遇到的问题记录
  17. 华硕ZX53VD笔记本的机械硬盘换成固态硬盘
  18. 计算机视觉寒假实习生面经
  19. 微信小程序复制文本方法
  20. 读论文:Charting the Right Manifold:Manifold Mixup for Few-shot Learning

热门文章

  1. 自建服务器选择标准,自建CDN如何选择服务器
  2. mplab java失败_【超菜鸟求助】编译时失败,以下是显示内容。
  3. ajax jq 图片上传请求头_前端常见面试 请求篇
  4. 438.找到字符串中所有字母异位词
  5. const数据成员的初始化
  6. 常用测试用例设计方法
  7. arm linux 删除大量文件,ARM Linux根文件系统(Root Filesystem)的制作
  8. linux全局查找-find,locate,whereis,which,type区别
  9. 实现链表翻转的两种方法
  10. 最新最全latex在sublime上的配置步骤全解