一 、
映射维护方法
1
、查询所有索引的映射:
GET
:
http://localhost:9200/_mapping
2
、创建映射(Postman)
post
请求:
http://localhost:9200/xc_course/doc/_mapping
{
"properties":{
"name":{
"type":"text"
},
"description":{
"type":"text"
},
"studymodel":{
"type":"keyword"
}
}
}
3
、更新映射
映射创建成功可以添加新字段,已有字段不允许更新。
4
、删除映射
通过删除索引来删除映射。
二、常用映射类型
1、
下图是
ES6.2
核心的字段类型如下:
![](https://img-blog.csdnimg.cn/20191109144449156.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5Njg5NjA1,size_16,color_FFFFFF,t_70)
2、字符串包括
text
和
keyword
两种类型:
1
、
text
1
)
analyzer
通过
analyzer
属性指定分词器。
下边指定
name
的字段类型为
text
,使用
ik
分词器的
ik_max_word
分词模式。
"name": { "type": "text", "analyzer":"ik_max_word" }
上边指定了analyzer
是指在索引和搜索都使用
ik_max_word
,如果单独想定义搜索时使用的分词器则可以通过
search_analyzer
属性。
对于
ik
分词器建议是索引时使用
ik_max_word
将搜索内容进行细粒度分词,搜索时使用
ik_smart
提高搜索精确性。
"name": { "type": "text", "analyzer":"ik_max_word", "search_analyzer":"ik_smart" }
2
)
index
通过
index
属性指定是否索引。
默认为
index=true
,即要进行索引,只有进行索引才可以从索引库搜索到。
但是也有一些内容不需要索引,比如:商品图片地址只被用来展示图片,不进行搜索图片,此时可以将
index
设置
为
false
。
删除索引,重新创建映射,将
pic
的
index
设置为
false
,尝试根据
pic
去搜索,结果搜索不到数据
"pic": { "type": "text", "index":false }
3
)
store
是否在
source
之外存储,每个文档索引后会在
ES
中保存一份原始文档,存放在
"_source"
中,一般情况下不需要设置
store
为
true
,因为在
_source
中已经有一份原始文档了。
3、测试
1)删除
xc_course/doc
下的映射
2)创建新映射:
Post
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"
},
"pic":{
"type":"text",
"index":false
},
"studymodel":{
"type":"text"
}
}
}
3)
插入文档:
put http://localhost:9200/xc_course/doc/4028e58161bcf7f40161bcf8b77c0000
{
"name":"Bootstrap开发框架",
"description":"Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的 精美界面效果。",
"pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"studymodel":"201002"
}
4)
查询测试:
Get http://localhost:9200/xc_course/_search?q=name:开发
Get http://localhost:9200/xc_course/_search?q=description:开发
Get http://localhost:9200/xc_course/_search? q=pic:group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg
Get http://localhost:9200/xc_course/_search?q=studymodel:201002
通过测试发现:name和description都支持全文检索,pic不可作为查询条件。
4、keyword关键字字段
1) keyword
字段为关键字字段,通常搜索
keyword
是按照整体搜 索,所以创建keyword
字段的索引时是不进行分词的,比如:邮政编码、手机号码、身份证等。
keyword
字段通常 用于过虑、排序、聚合等。
2)
测试
更改映射:
{
"properties":{
"studymodel":{
"type":"keyword"
},
"name":{
"type":"keyword"
}
}
}
插入文档:
{
"name":"java编程基础",
"description":"java语言是世界第一编程语言,在软件开发领域使用人数最多。",
"pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"studymodel":"201001"
}
根据
studymodel
查询文档
搜索:
http://localhost:9200/xc_course/_search?q=name:java
name
是
keyword
类型,所以查询方式是精确查询。
5、
date
日期类型
日期类型不用设置分词器。
通常日期类型的字段用于排序。
1) format
通过
format
设置日期格式
例子:
下边的设置允许
date
字段存储年月日时分秒、年月日及毫秒三种格式。
{
"properties":{
"timestamp":{
"type":"date",
"format":"yyyy‐MM‐dd HH:mm:ss||yyyy‐MM‐dd"
}
}
}
插入文档:
{
"name":"spring开发基础",
"description":"spring 在java领域非常流行,java程序员都在用。",
"studymodel":"201001",
"pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"timestamp":"2018‐07‐04 18:28:58"
}
6、数值类型
下边是
ES
支持的数值类型:
![](https://img-blog.csdnimg.cn/20191109150121681.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5Njg5NjA1,size_16,color_FFFFFF,t_70)
1) 尽量选择范围小的类型,提高搜索效率
2) 对于浮点数尽量用比例因子,比如一个价格字段,单位为元,我们将比例因子设置为
100
这在
ES
中会按 分 存
储,映射如下:
"price": { "type": "scaled_float", "scaling_factor": 100 }
由于比例因子为100,如果我们输入的价格是23.45则ES中会将23.45乘以100存储在ES中。
如果输入的价格是23.456,ES会将23.456乘以100再取一个接近原始值的数,得出2346。
使用比例因子的好处是整型比浮点型更易压缩,节省磁盘空间。
如果比例因子不适合,则从下表选择范围小的去用:
![](https://img-blog.csdnimg.cn/20191109150316383.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM5Njg5NjA1,size_16,color_FFFFFF,t_70)
更新已有映射,并插入文档:
http://localhost:9200/xc_course/doc/3
{
"name":"spring开发基础",
"description":"spring 在java领域非常流行,java程序员都在用。",
"studymodel":"201001",
"pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"timestamp":"2018‐07‐04 18:28:58",
"price":38.6
}
二、索引管理
1 、
搭建java工程
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>
2、创建搜索工程
1)
创建搜索工程(
maven
工程):
xc-service-search
,添加
RestHighLevelClient
依赖及
junit
依赖。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>xc-framework-parent</artifactId>
<groupId>com.xuecheng</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../xc-framework-parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.xuecheng</groupId>
<artifactId>xc-service-search</artifactId>
<dependencies>
<dependency>
<groupId>com.xuecheng</groupId>
<artifactId>xc-framework-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.xuecheng</groupId>
<artifactId>xc-framework-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.xuecheng</groupId>
<artifactId>xc-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
</project>
2) 配置文件 application.yml
server:
port: ${port:40100}
spring:
application:
name: xc-search-service
xuecheng:
elasticsearch:
hostlist: ${eshostlist:127.0.0.1:9200} #多个结点中间用逗号分隔
3) 配置类 ElasticsearchConfig
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;
@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();
}
}
4、启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Administrator
* @version 1.0
**/
@SpringBootApplication
public class SearchApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(SearchApplication.class, args);
}
}
5、创建索引库等(在test路径下创建TestIndex测试类)
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author Administrator
* @version 1.0
**/
@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" +
" \"studymodel\":{\n" +
" \"type\":\"keyword\"\n" +
" },\n" +
" \"name\":{\n" +
" \"type\":\"keyword\"\n" +
" },\n" +
" \"description\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\":\"ik_max_word\",\n" +
" \"search_analyzer\":\"ik_smart\"\n" +
" },\n" +
" \"pic\":{\n" +
" \"type\":\"text\",\n" +
" \"index\":false\n" +
" }\n" +
" \t}\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");
//操作索引的客户端
IndicesClient indices = client.indices();
//执行删除索引
DeleteIndexResponse delete = indices.delete(deleteIndexRequest);
//得到响应
boolean acknowledged = delete.isAcknowledged();
System.out.println(acknowledged);
}
}
2)添加文档
1、API
格式如下: PUT /{index}/{type}/{id} { "fifield": "value", ... }
如果不指定
id
,
ES
会自动生成。
一个例子:
put
http://localhost:9200/xc_course/doc/3
{
"name":"spring开发基础",
"description":"spring 在java领域非常流行,java程序员都在用。",
"studymodel":"201001",
"pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"timestamp":"2018‐07‐04 18:28:58",
"price":38.6
}
2、java操作
//添加文档
@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);
//通过client进行http的请求
IndexResponse indexResponse = client.index(indexRequest);
DocWriteResponse.Result result = indexResponse.getResult();
System.out.println(result);
}
3)查询文档
格式如下:
GET /{index}/{type}/{id}
//查询文档
@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)
更新文档
1、API
ES
更新文档的顺序是:先检索到文档、将原来的文档标记为删除、创建新文档、删除旧文档,创建新文档就会重建
索引。
通过请求
Url
有两种方法:
a
、完全替换
Post
:
http://localhost:9200/xc_test/doc/3
{
"name":"spring开发基础",
"description":"spring 在java领域非常流行,java程序员都在用。",
"studymodel":"201001",
"pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
"timestamp":"2018‐07‐04 18:28:58",
"price":40
}
b
、局部更新
下边的例子是只更新
price
字段。
post:
http://localhost:9200/xc_test/doc/3/_update
{ "doc":{"price":66.6} }
2、java 操作
使用
ClientApi
更新文档的方法同上边第二种局部更新方法。
可以指定文档的部分字段也可以指定完整的文档内容。
@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);
}
5} 删除文档
1、API
根据
id
删除,格式如下:
DELETE/{index}/{type}/{id}
搜索匹配删除,将搜索出来的记录删除,格式如下:
POST/{index}/{type}/_delete_by_query 下边是搜索条件例子:
{
"query":{
"term":{
"studymodel":"201001"
}
}
}
上边例子的搜索匹配删除会将
studymodel
为
201001
的记录全部删除。
2、Java 操作
//根据id删除文档
@Test
public void testDelDoc() throws IOException {
//删除文档id
String 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
删除。