ElasticSearch的使用

ElasticSearch

概念:简称es,是一个开源的高扩展的分布式全文检索引擎,可以近乎实时的存储、检索数据。

ES对比Solr:

  • Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能;
  • Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
  • Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提供;
  • Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于 Elasticsearch

一 ElastisSearch相关概念

Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。Elasticsearch比传统关系型数据库如下:

Relational DB ‐> Databases ‐> Tables ‐> Rows ‐> Columns

Elasticsearch ‐> Indices ‐> Types ‐> Documents ‐> Fields

1 核心概念

索引 index

类型 type

字段 field

映射 mapping

文档 document

接近实时 NRT

集群 cluster

节点 node

分片和复制 shards&replicas

二 客户端操作/Postman操作

1 接口语法(增删改查)

创建索引和映射

  • 1 索引和映射一起创建
method: PUT
url: localhost: 9200 / blog
body: {
	"mappings": {
		"article": {
			"properties": {
				"id": {
					"type": "long",
					"store": true,
					"index": true
				},
				"title": {
					"type": "text",
					"store": true,
					"index": true,
					"analyzer": "standard"
				},
				"content": {
					"type": "text",
					"store": true,
					"index": true,
					"analyzer": "standard"
				}
			}
		}
	}
}
  • 2 先创建索引,再创建映射

创建索引

method:PUT url:localhost:9200/blog 

创建mapping

method: POST 
url: localhost: 9200 / blog / article / _mapping 
body: {
	"hello": {
		"properties": {
			"id": {
				"type": "long",
				"store": true
			},
			"title": {
				"type": "text",
				"store": true,
				"index": true,
				"analyzer": "standard"
			},
			"content": {
				"type": "text",
				"store": true,
				"index": true,
				"analyzer": "standard"
			}
		}
	}
}
  • 删除索引
method:DELETE  url localhost:9200/blog 
  • 向索引库添加文档
method:POST url localhost:9200/index/type/(1)_id
(url中id是数据库中实际的id,跟json中没有关系,不添加id自动生成字符串id)
body:{
    "id":100,
    "title":"",
    "content":""
}
  • 修改文档:

es是用**Lucene作为核心的,所以修改操作的原理是先删除后增加。实际是根据_id覆盖。

查询:

#根据 Id
method:GET url localhost:port/index/type/_id
#关键字
POST  	localhost:port/index/type/_search(命令)
body:
{
    "query":{
        "term":{
            "title":"关键词"
        }
    }
}
#query_string查询(指定一个查询域)
POST  	localhost:port/index/type/_search(命令)
body:
{
    "query":{
        "query_string":{
             "default_field":"title",
             "query":"query——string"(进行分词)
        }
    }
}

三 IK分词器和Elastic Search集成使用

IK提供了两个分词算法ik_smart 和 ik_max_word;其中 ik_smart 为最少切分,ik_max_word为最细粒度划分。

示例:

http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员 

四 Elastic Searchj集群

实际操作中都是以集群启动服务

1 集群cluster

一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。

2 节点node

一个节点是集群中的一个服务器

3 分片shards

当一个索引具有足够大空间占用的时候,而节点不具备这么大的磁盘空间,或者单个节点搜索太慢,es提供将索引划分成多片的方法。

4 复制replicas

在云环境中,失败随时可能存在,es允许创建分片的一份或者多份的复制。(故障转移机制)。

5 集群搭建

准备3台服务器:

修改每台服务器的elasticsearch.yml配置文件

#节点1的配置信息:
#集群名称,保证唯一
cluster.name: my‐elasticsearch
#节点名称,必须不一样
node.name: node‐1/node-2/node-3
#必须为本机的ip地址
network.host: 127.0.0.1
#服务端口号,在同一机器下必须不一样
http.port: 9200
#集群间通信端口号,在同一机器下必须不一样
transport.tcp.port: 9300
#设置集群自动发现机器ip集合
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300"
                ,"127.0.0.1:9301"
                ,"127.0.0.1:9302"]

五 elastic search的原生Java操作

重点:如何创建客户端对象

Settings settings = Settings.builder() .put("cluster.name", 集群名称).build(); TransportClient client = new PreBuiltTransportClient(settings) .addTransportAddress(new InetSocketTransportAddress(InetAddress .getByName("127.0.0.1"), port)); 

1 创建工程导入坐标

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>5.6.8</version>
</dependency>
<!--客户端依赖-->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>5.6.8</version>
</dependency>

2 创建索引 index

//创建索引
public void test1() throws Exception{
    // 创建Client连接对象
    Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
    TransportClient client = new PreBuiltTransportClient(settings)
        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
    //创建名称为blog2的索引
    client.admin().indices().prepareCreate("blog2").get();
    //释放资源
    client.close();
}

3 创建映射mapping

public void test3() throws Exception{
    // 创建Client连接对象
    Settings settings = Settings.builder().put("cluster.name"
    , "my-elasticsearch").build();
    TransportClient client = new PreBuiltTransportClient(settings)
        .addTransportAddress(new InetSocketTransportAddress(InetAddress
        .getByName("127.0.0.1"), 9300));
    
    // 添加映射
    /**
         * 格式:
         * "mappings" : {
             "article" : {
                "dynamic" : "false",
                 "properties" : {
                    "id" : { "type" : "string" },
                     "content" : { "type" : "string" },
                    "author" : { "type" : "string" }
                 }
            }
         }
         */
    XContentBuilder builder = XContentFactory.jsonBuilder()
        .startObject()
        .startObject("article")
        .startObject("properties")
        .startObject("id")
        .field("type", "integer").field("store", "yes")
        .endObject()
        .startObject("title")
        .field("type", "string").field("store", "yes")
        .field("analyzer", "ik_smart")
        .endObject()
        .startObject("content")
        .field("type", "string").field("store", "yes")
        .field("analyzer", "ik_smart")
        .endObject()
        .endObject()
        .endObject()
        .endObject();
    // 创建映射
    PutMappingRequest mapping = Requests.putMappingRequest("blog2")
        .type("article").source(builder);
    client.admin().indices().putMapping(mapping).get();
    //释放资源
    client.close();
}

4 建立文档document/批量插入

  • 通过XContentBuilder
//创建文档(通过XContentBuilder)
public void test4() throws Exception{
    // 创建Client连接对象
    Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
    TransportClient client = new PreBuiltTransportClient(settings)
        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

    //创建文档信息
    XContentBuilder builder = XContentFactory.jsonBuilder()
        .startObject()
        .field("id", 1)
        .field("title", "ElasticSearch是一个基于Lucene的搜索服务器")
        .field("content",
               "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。")
        .endObject();

    // 建立文档对象
    /**
         * 参数一blog1:表示索引对象
         * 参数二article:类型
         * 参数三1:建立id
         */
    client.prepareIndex("blog2", "article", "1").setSource(builder).get();

    //释放资源
    client.close();
}
  • 通过json转换实体

1)创建Article实体

public class Article {
    private Integer id;
    private String title;
    private String content;
       getter/setter...
}

2)添加jackson坐标

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-core</artifactId>
   <version>2.8.1</version>
</dependency>
<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.8.1</version>
</dependency>
<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-annotations</artifactId>
   <version>2.8.1</version>
</dependency>

3)代码实现

@Test
//创建文档(通过实体转json)
public void test5() throws Exception{
   // 创建Client连接对象
   Settings settings = Settings.builder()
   .put("cluster.name", "my-elasticsearch").build();
   TransportClient client = new PreBuiltTransportClient(settings)
      .addTransportAddress(new InetSocketTransportAddress(InetAddress
      .getByName("127.0.0.1"), 9300));// 描述json 数据
   //{id:xxx, title:xxx, content:xxx}
   Article article = new Article();
   article.setId(2);
   article.setTitle("搜索工作其实很快乐");
   article.setContent("我们希望我们的搜索解决方案要快。");
​
   ObjectMapper objectMapper = new ObjectMapper();// 建立文档
   client.prepareIndex("blog2", "article", article.getId().toString())
       //.setSource(objectMapper.writeValueAsString(article)).get();
      .setSource(objectMapper.writeValueAsString(article)
      .getBytes(), XContentType.JSON).get();//释放资源
   client.close();
}
  • 批量插入

即在上面的代码实现里,把创建实体Article,描述json;建立文档改为循环操作。

5 查询文档操作

  • 创建es客户端TransportClient
  • 设置搜索条件获得搜索响应
  • 遍历响应结果
public void testTermQuery() throws Exception{
    //1、创建es客户端连接对象
    Settings settings = Settings.builder()
    .put("cluster.name", "my-elasticsearch").build();
    TransportClient client = new PreBuiltTransportClient(settings)
        .addTransportAddress(new InetSocketTransportAddress(InetAddress
        .getByName("127.0.0.1"), 9300));
//2、设置搜索条件
    #1关键字搜索
    SearchResponse searchResponse = client.prepareSearch("blog2")
        .setTypes("article")
        .setQuery(QueryBuilders.termQuery("content", "搜索")).get();
    #2字符串查询
SearchResponse searchResponse = client.prepareSearch("blog2")
        .setTypes("article")
        .setQuery(QueryBuilders.queryStringQuery("搜索")).get();
    #3根据Id
        //client对象为TransportClient对象
        SearchResponse searchResponse = client.prepareSearch("blog1")
                .setTypes("article")
                //设置要查询的id
                .setQuery(QueryBuilders.idsQuery().addIds("test002"))
                //执行查询
                .get();
    
    //3、遍历搜索结果数据
    SearchHits hits = searchResponse.getHits(); // 获取命中次数,查询结果有多少对象
    System.out.println("查询结果有:" + hits.getTotalHits() + "条");
    Iterator<SearchHit> iterator = hits.iterator();
    while (iterator.hasNext()) {
        SearchHit searchHit = iterator.next(); // 每个查询对象
        System.out.println(searchHit.getSourceAsString()); // 获取字符串格式打印
        System.out.println("title:" + searchHit.getSource().get("title"));
    }

    //4、释放资源
    client.close();

}

6 查询文档分页操作

//1 .创建客户端
//2 .设置搜索条件
SearchRequestBuilder searchRequestBuilder 
    = client.prepareSearch("blog2").setTypes("article")
        .setQuery(QueryBuilders.matchAllQuery());//默认每页10条记录
//setFrom():从第几条开始检索,默认是0。
//setSize():每页最多显示的记录数。
searchRequestBuilder.setFrom(0).setSize(5);
SearchResponse searchResponse = searchRequestBuilder.get();
//获取命中次数
SearchHits hits = searchResponse.getHits();
hits.getTotalHits();
//迭代器遍历
Iterator<SearchHit> iterator = hits.iterator();
while (iterator.hasNext()) {
    }
//释放资源

7 查询结果高亮操作

  • 概念:在进行关键字搜索时,搜索出的内容中的关键字会显示不同的颜色,称之为高亮。
  • 原理:查看html源码可以看到es对html中关键字的样式和标签进行了设置,但是需要告诉es用什么标签和样式进行包裹。
  • Java高亮实现
//获取TransportClient,SearchRequestBuilder
//设置高亮数据
HighlightBuilder hiBuilder=new HighlightBuilder();
hiBuilder.preTags("<font style='color:red'>");
hiBuilder.postTags("</font>");
hiBuilder.field("title");
searchRequestBuilder.highlighter(hiBuilder);
//获取查询结果数据
//对应操作
hit.getHighlightFields();//获取高亮内容
//获取高亮集合
hit.getHighlightFields().get("title").getFragments();
//释放资源

六 Spring Data ElasticSearch的使用

Spring Data**是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。Spring Data可以极大的简化JPA的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。

Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API进行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。

1 环境搭建入门

  • maven工程加入坐标
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>5.6.8</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>5.6.8</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-elasticsearch</artifactId>
    <version>3.0.5.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>org.elasticsearch.plugin</groupId>
            <artifactId>transport-netty4-client</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  • applicationContext.xml添加配置:

1配置elasticsearch:transport-client

2配置包扫描器

3配置模板对象ElasticSearchTemplate

<!-- 扫描Dao包,自动创建实例 -->
<elasticsearch:repositories base-package="com.pw.dao"/>
<!-- 配置elasticSearch的连接 -->
    <!-- 配置elasticSearch的连接 -->
<elasticsearch:transport-client id="client" 
    cluster-nodes="localhost:9300" 
    cluster-name="my-elasticsearch"/>
<!-- ElasticSearch模版对象 -->
<bean id="elasticsearchTemplate" 
class="org.springframework.data.elasticsearch.core
.ElasticsearchTemplate">
    <constructor-arg name="client" ref="client"></constructor-arg>
</bean>
  • 创建操作接口实现springdata elasticsearch包下的Elastic Search Repository<>
public interface ArticleRepository extends ElasticsearchRepository<Article,Integer> {
} 
  • 创建实体类并配置
@Document(indexName="blog3",type="article")
@Lombok
public class Article {
    @Id
    @Field(store=true, index = false,type = FieldType.Integer)
    private Integer id;
    @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    private String title;
    @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    private String content;
}
/*
其中,注解解释如下:
@Document(indexName="blob3",type="article"):
    indexName:索引的名称(必填项)
    type:索引的类型
@Id:主键的唯一标识
@Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type = FieldType.text)
    index:是否设置分词
    analyzer:存储时使用的分词器
    searchAnalyze:搜索时使用的分词器
    store:是否存储
    type: 数据类型
*/

七 Spring Data ElasticSearch常用操作

1 增啥改查

2 查询命名规则

3 Elasticsearch的原生查询对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值