全文检索elasticsearch

全文检索ElasticSearch

1 ElasticSearch介绍

1.1.介绍

1、ElasticSearch是一个基于Lucene的高扩展的分布式搜索服务器,支持开箱即用。

2、ElasticSearch隐藏了Lucene的复杂性,对外提供Restful 接口来操作索引、搜索。

1.2.原理与应用

逻辑结构部分是一个倒排索引表:

1、将要搜索的文档内容分词,所有不重复的词组成分词列表

2、将搜索的文档最终以Document方式存储起来

3、每个词和docment都有关联。

2 ElasticSearch安装

2.1.windos的安装

下载ES: https://www.elastic.co/downloads/past-releases

解压:

bin:脚本目录,包括:启动、停止等可执行脚本

config:配置文件目录

data:索引目录,存放索引文件的地方 (没有的话自己创建)

logs:日志目录 (没有的话自己创建)

modules:模块目录,包括了es的功能模块

plugins :插件目录,es支持插件机制

2.2.配置文件

config目录下的elasticsearch.yml文件里配置参数

cluster.name: el
node.name: el_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
bootstrap.memory_lock: false
node.max_local_storage_nodes: 2

path.data: D:\IDEA\ElasticSearch\elasticsearch-1\data (换为你自己的路径)
path.logs: D:\IDEA\ElasticSearch\elasticsearch-1\logs (换为你自己的路径)

http.cors.enabled: true
http.cors.allow-origin: /.*/

2.3.启动

进入bin目录,在cmd下运行:elasticsearch.bat

浏览器输入:http://localhost:9200

3 ES快速入门

3.1.创建索引库

ES的索引库是一个逻辑概念,它包括了分词列表及文档列表,同一个索引库中存储了相同类型的文档。它就相当于MySQL中的表,或相当于Mongodb中的集合

索引(名词):ES是基于Lucene构建的一个搜索服务,它要从索引库搜索符合条件索引数据。

索引(动词):索引库刚创建起来是空的,将数据添加到索引库的过程称为索引。

1)使用postman发送:put http://localhost:9200/索引库名称

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

3.2.创建映射

3.2.1.概念说明:

与关系数据库的对比

文档(Document)----------------Row记录

字段(Field)-------------------Columns 列

3.2.2.创建映射

发送:post http://localhost:9200/索引库名称/类型名称/_mapping

类型名称:可自定义,在ES6.0中要弱化类型的概念,给它起一个没有具体业务意义的名称。

创建映射相当于关系数据库中创建表结构

{ 
"properties":
  { 
        "name":
        {
        "type": "text" 
        },
        "description":
        { 
        "type": "text"
        },
        "studymodel":
        { 
         "type": "keyword" 
        }
   }
}

3.3.创建文档

ES中的文档相当于MySQL数据库表中的记录(数据)。

发送:put 或Post http://localhost:9200/xc_course/doc/id

id: 自定义值,如果不指定则会自动生成id

{
  "name":"Bootstrap开发框架",
  "description":"Bootstrap",
  "studymodel":"201001"
}

3.4.搜索文档

1、根据课程id查询文档

发送:get http://localhost:9200/xc_course/doc/1

2、查询所有记录

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

3、查询名称中包括spring 关键字的的记录

发送:get http://localhost:9200/xc_course/doc/_search?q=name:bootstrap

4、查询学习模式为201001的记录

发送 get http://localhost:9200/xc_course/doc/_search?q=studymodel:201001

4 IK分词器

4.1.安装IK分词器

下载IK分词器:(Github地址:https://github.com/medcl/elasticsearch-analysis-ik)

解压,并将解压的文件拷贝到ES安装目录的plugins下的ik目录下;

4.2.ik分词器的两种模式

1.ik_max_word :最细粒度拆分;

2.ik_smart: 最粗粒度拆分;

4.3.自定义词库

iK分词器自带一个main.dic的文件,此文件为词库文件

5 映射

1、查询所有索引的映射:

GET: http://localhost:9200/_mapping

2、更新映射

映射创建成功可以添加新字段,已有字段不允许更新。

3、删除映射

通过删除索引来删除映射。

5.1.常用映射类型

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;

  1. keyword关键字字段

keyword字段为关键字字段,通常搜索keyword是按照整体搜索,所以创建keyword字段的索引时是不进行分词的,是需要全部匹配;

6 索引管理

6.1.搭建工程

添加依赖

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

配置文件application.yml

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

配置类:

@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();
    }

}

6.2.使用Java客户端

6.2.1.创建索引库

public class TestIndex {
    @Autowired
    RestHighLevelClient client;

    @Autowired
    RestClient restClient;
     /**
     * 创建索引库
     */
    @Test
    public void testCreateIndexx() throws IOException {
        //创建索引对象
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("el_01");
        //设置参数
        createIndexRequest.settings(Settings.builder().put("number_of_shards","1").put("number_of_replicas","0"));
        //指定映射
        createIndexRequest.mapping("doc","{\n" +
                "\t\"properties\": {\n" +
                "\t   \"name\": {\n" +
                "\t   \t\"type\": \"text\",\n" +
                "\t    \"analyzer\": \"ik_max_word\",\n" +
                "\t    \"search_analyzer\": \"ik_smart\"\n" +
                "\t   },\n" +
                "\t   \"description\": {\n" +
                "\t   \t\"type\": \"text\",\n" +
                "\t    \"analyzer\": \"ik_max_word\",\n" +
                "\t    \"search_analyzer\": \"ik_smart\"\n" +
                "\t   },\n" +
                "\t   \"pic\": {\n" +
                "\t   \t\"type\": \"text\",\n" +
                "\t   \t\"index\": false\n" +
                "\t   },\n" +
                "\t   \"studymodel\": {\n" +
                "\t   \t\"type\": \"text\"\n" +
                "\t   }\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 testAddDoc() throws IOException {
        // 准备json串
        Map<String, Object> map = new HashMap<>();
        map.put("name","spring cloud实战课程");
        map.put("description","BootStrap是放松放松放松,李智是黑马程序员,此开发框架在实际中大量使用");
        map.put("studymodel","20200");
        map.put("pic","/img/");
        //创建添加索引的请求对象
        IndexRequest indexRequest = new IndexRequest("xc_course", "doc");
        //文档内容
        indexRequest.source(map);
        //通过client进行http请求
        IndexResponse index = client.index(indexRequest);
        DocWriteResponse.Result result = index.getResult();
        System.out.println(result);
    }
     /**
     * 查询文档
     */
    @Test
    public void testGetDoc() throws IOException {
        //查询的请求对象
        GetRequest getRequest = new GetRequest("xc_course", "doc", "iCzcUnQB0UogVLzdiAD9");
        GetResponse documentFields = client.get(getRequest);
        //得到文档内容
        Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();
        System.out.println(sourceAsMap);
    }

    /**
     * 修改文档
     */
    @Test
    public void testUpdateDoc() throws IOException {
        //更新的请求对象
        UpdateRequest updateRequest = new UpdateRequest("xc_course", "doc", "iCzcUnQB0UogVLzdiAD9");
        Map<String, Object> map = new HashMap<>();
        map.put("name","spring");
        updateRequest.doc(map);
        UpdateResponse update = client.update(updateRequest);
        //得到文档内容
        RestStatus status = update.status();
        System.out.println(status);
    }
    /**
 * 删除索引库
 */
    @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);
    }
   }
posted @ 2020-09-11 10:53  撑起一片阳光  阅读(1823)  评论(0编辑  收藏  举报