ElasticSearch简介
ElasticSearch:智能搜索,分布式搜索引擎。
是ELK的一个组成。是一个产品,而且是非常完善的产品,ELK代表的是:E就是ElasticSearch,L就是Logstach,K即使Kibana
E:ElasticSearch 搜索和分析的功能;
L:Logstach 搜索数据的功能,类似于flume(使用方法几乎跟flume一模一样)。是日志收集系统
K:Kibana 数据可视化(分析),可以用图标的方式来去展示,文不如表,表不如图,是可视化平台。
ElasticSearch优点
- 分布式的功能
- 数据高可用,集群高可用
- API更简单
- API更高级
- 支持的语言很多
- 支持PB级别的数据
- 完成搜索的功能和分析功能
- 基于Luncene,隐藏了Luncene的复杂性,提供简单的API
- ElasticSearch性能比HBase高,咱们的竞价引擎最后还是要存到ES中的
搜索引擎原理
- 反向索引又叫倒排索引,是根据文章内容中的关键字建立索引。
- 搜索引擎原理就是建立反向索引。
- ES在Luncene的基础上进行封装,实现了分布式搜索引擎。
- ES中的索引、类型和文档的概念比较重要,类似于MySQL中的数据库、表和行。
- ES也是Master-slave架构,也实现了数据库的分片和备份。
- ES一个典型的应用就是ELK日志分析系统。
ES支持的语言
Cur/java/c#/python/javaScript/hph/perl/ruby
ES的作用
- 全文搜索:类似 select * from product where product_name like '%牙膏%'类似百度效果(电商搜索的效果)
- 结构化搜索:类似 select * from product where product_id = ‘1’
- 数据分析类似 select count (*) from product
ES的核心概念
- NRT(Near Realtime)近实时
- cluster集群,ES是一个分布式的系统:ES直接解压不需要配置就可以使用,在hadoop1上解压一个ES,在hadoop2上解压了一个ES,接下来把这两个ES启动起来。他们就构成了一个集群。在ES里面默认有一个配置,clustername 默认值就是ElasticSearch,如果这个值是一样的就属于同一个集群,不一样的值就是不一样的集群。
- Node节点,就是集群中的一台服务器
- Index索引(索引库):我们为什么使用ES?因为想把数据存进去,然后再查询出来。我们在使用Mysql或者Oracle的时候,为了区分数据,我们会建立不同的数据库,库下面还有表的。其实ES功能就像一个关系型数据库,在这个数据库我们可以往里面添加数据,查询数据。ES中的索引非传统索引的含义,ES中的索引是存放数据的地方,是ES中的一个概念词汇index类似于我们Mysql里面的一个数据库 create database user; 好比就是一个索引库
- type类型:类型是用来定义数据结构的在每一个index下面,可以有一个或者多个type,好比数据库里面的一张表。相当于表结构的描述,描述每个字段的类型。
- document(文档):文档就是最终的数据了,可以认为一个文档就是一条记录。在ES里面最小的数据单元,就好比表里面的一条数据
- Field字段:好比关系型数据库中列的概念,一个documenr有一个或者多个filed组成。
- shard(分片):一台服务器,无法存储大量的数据,ES把一个index里面的数据,分为多个shard,分布式的存储在各个服务器上面。kafka:为什么支持分布式的功能,因为里面是有topic,支持分区的概念。所以topic A可以存在不同的节点上面。就可以支持海量数据和高并发,提升性能和吞吐量。我们为了保证数据的安全,我们引入了replica的概念,跟hdfs里面的概念是一个意思。可以保证我们数据的安全。在ES集群中,我们一模一样的数据有多份,能正常提供查询和插入的分片我们叫做 primary shard,其余的我们就管他们叫做 replica shard(备份的分片)当我们去查询数据的时候,我们数据是有备份的,它会同时发出命令让我们有数据的机器去查询结果,最后谁的查询结果快,我们就要谁的数据(这个不需要我们去控制,它内部就自己控制了)。
在默认情况下,我们创建一个库的时候,默认会帮我们创建5个主分片(primary shrad)和5个副分片(replica shard),所以说正常情况下是有10个分片的。
同一个节点上面,副本和主分片是一定不会在一台机器上面的,就是拥有相同数据的分片,是不会在同一个节点上面的。
所以当你有一个节点的时候,这个分片是不会把副本存在这仅有的一个节点上的,当你新加入了一台节点,ES会自动的给你在新机器上创建一个之前分片的副本。
ElasticSearch客户端
TransportClient(传输客户端)
(强烈建议使用Java High Level REST Clien而不是TransportClient),
TransportClient
,从 Elasticsearch 7 开始已弃用,并将在 Elasticsearch 8 中删除。(请参阅 Elasticsearch 文档)。Spring Data Elasticsearch 将支持它
TransportClient
,只要它在使用的 Elasticsearch版本中可用,但自 4.0 版以来已弃用使用它的类
@ConfigurationpublicclassTransportClientConfigextendsElasticsearchConfigurationSupport{@Beanpublic Client elasticsearchClient()throws UnknownHostException {
Settings settings = Settings.builder().put("cluster.name","elasticsearch").build();
TransportClient client =newPreBuiltTransportClient(settings);
client.addTransportAddress(newTransportAddress(InetAddress.getByName("127.0.0.1"),9300));return client;}@Bean(name ={"elasticsearchOperations","elasticsearchTemplate"})public ElasticsearchTemplate elasticsearchTemplate()throws UnknownHostException {returnnewElasticsearchTemplate(elasticsearchClient());}}// ...
IndexRequest request =newIndexRequest("spring-data","elasticsearch",randomID()).source(someObject).setRefreshPolicy(IMMEDIATE);
IndexResponse response = client.index(request);//TransportClient必须使用集群名称进行配置。//连接客户端的主机和端口
Java High Level REST Clien(高级REST客户端)
Java High Level REST Clien是ElasticSearch的默认客户端,它提供了直接的代替,TransportClient因为它接受并返回完全相同的请求/响应对象,因此依赖于ElaticSearch核心项目。异步调用在客户端管理的线程池上进行操作,并且需要在请求完成时通知回调。
@ConfigurationpublicclassRestClientConfigextendsAbstractElasticsearchConfiguration{@Override@Beanpublic RestHighLevelClient elasticsearchClient(){final ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo("localhost:9200").build();return RestClients.create(clientConfiguration).rest();}}// ...@Autowired
RestHighLevelClient highLevelClient;
RestClient lowLevelClient = highLevelClient.lowLevelClient();// ...
IndexRequest request =newIndexRequest("spring-data","elasticsearch",randomID()).source(singletonMap("feature","high-level-rest-client")).setRefreshPolicy(IMMEDIATE);
IndexResponse response = highLevelClient.index(request);//使用构建器提供集群地址、设置默认值httpHeaders或启用SSL。//创建RestHighLevelClient。//也可以获取lowLevelRest客户端
测试config配置如下:
@ConfigurationpublicclassEsConfig{//配置本机地址以及端口@Value("${spring.elasticsearch.hostname}")private String hostname;@Value("${spring.elasticsearch.port}")privateint port;/**
* LowLevelRestConfig
*/@Beanpublic RestClient restClient(){// 如果有多个从节点可以持续在内部new多个HttpHost,参数1是IP,参数2是端口,参数3是通信协议
RestClientBuilder clientBuilder = RestClient.builder(newHttpHost(hostname, port,"http"));// 设置Header编码
Header[] defaultHeaders ={newBasicHeader("content-type","application/json")};
clientBuilder.setDefaultHeaders(defaultHeaders);return clientBuilder.build();}/**
* HighLevelRestConfig
*/@Beanpublic RestHighLevelClient restHighLevelClient(){// 如果有多个从节点可以持续在内部new多个HttpHost,参数1是IP,参数2是端口,参数3是通信协议returnnewRestHighLevelClient(RestClient.builder(newHttpHost(hostname, port,"http")));}}
ReactiveElasticsearchClient(反应试客户端)
ReactiveElaticsearchClient是一个基于WebClient,它使用Elasticsearch核心项目提供的请求/响应对象。调用直接在响应式堆栈上操作,而不是将异步(线程池绑定)响应包装到响应式类型中。
staticclassConfig{@Bean
ReactiveElasticsearchClient client(){
ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo("localhost:9200","localhost:9291").withWebClientConfigurer(webClient ->{
ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder().codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)).build();return webClient.mutate().exchangeStrategies(exchangeStrategies).build();}).build();return ReactiveRestClients.create(clientConfiguration);}}// ...
Mono<IndexResponse> response = client.index(request ->
request.index("spring-data").type("elasticsearch").id(randomID()).source(singletonMap("feature","reactive-client")).setRefreshPolicy(IMMEDIATE););//使用构建器提供集群地址、设置默认值HttpHeaders或启用SSL。//在配置响应式客户端时,该withWebClientConfigurer钩子可用于自定义WebClient。
客户端配置
客户端行为可以通过
ClientConfiguration
允许设置 SSL、连接和套接字超时、标头和其他参数的选项来更改
HttpHeaders httpHeaders =newHttpHeaders();
httpHeaders.add("some-header","on every request")
ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo("localhost:9200","localhost:9291").useSsl().withProxy("localhost:8888").withPathPrefix("ela").withConnectTimeout(Duration.ofSeconds(5)).withSocketTimeout(Duration.ofSeconds(3)).withDefaultHeaders(defaultHeaders).withBasicAuth(username, password).withHeaders(()->{
HttpHeaders headers =newHttpHeaders();
headers.add("currentTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));return headers;}).// ... other options.build();//定义默认标题(如果需要自定义)//使用构建器提供集群地址、设置默认值HttpHeaders或启用SSL。//可选择启用SSL。//(可选)设置代理。//可选地设置路径前缀,主要用于在某些反向代理后面的不同集群时。//设置连接超时。默认值为10秒。//设置套接字超时。默认值为5秒。//可选的设置标题。//添加基本身份验证。//可以指定一个Supplier<Header>函数,在每次将请求发送到Elasticsearch之前调用该函数——例如:当前时间写入标头中。
客户端日志
要查看实际发送到服务器和从服务器接收到的内容Request/Response需要打开传输级别的日志记录,如下面的片段所述。
<loggername="org.springframework.data.elasticsearch.client.WIRE"level="trace"/>
Elasticsearch对象映射
Spring Data Elasticsearch 对象映射是将Java对象(域实体)映射到存储在Elasticsearch中并返回Json表示的过程。
Spring Data Elasticsearch 的早期版本使用基于 Jackson 的转换,Spring Data Elasticsearch 3.2.x 引入了Meta Model Object Mapping。从 4.0 版开始,仅使用 Meta Object Mapping,不再使用基于 Jackson 的映射器,而是使用了
MappingElasticsearchConverter
。
移除基于Jackson的映射器的主要原因是:
- 字段的定义映射需要使用@JsonFormat或之类的注释来完成@JsonInclude。当相同的对象用于不同的基于Json的数据存储或通过基于Json的API发送时,这通常会出现问题。
- 自定义字段类型和格式也需要存储到Elasticsearch索引映射中。基于Jackson的注释没有完全提供表示Elasticsearch类型所需的所有信息。
- 字段不仅在从实体转换到实体时必须映射,而且在查询参数,返回数据和其他地方也必须映射。
使用MappingElasticsearchConverter now涵盖了使用所有这些情况。
元模型对象映射
基于元模型的方法使用域类型信息来读取/写入ElasticSearch。这允许Converter为特定域类型映射注册实例。
映射注释概述
使用
MappingElasticsearchConverter
元数据来驱动对象到文档的映射。元数据取自可以注释的实体属性
可以使用以下注释:
@Documen
t:在类级别应用以指示该类是映射到数据库的候选对象。其中比较重要的属性是: -indexName
:存储此实体的索引的名称。这可以包含一个 SpEL 模板表达式,如"log-#{T(java.time.LocalDate).now().toString()}"
-type
:映射类型。如果未设置,则使用类的小写简单名称。(自 4.0 版起已弃用)-shards
:索引的分片数。-replicas
:索引的副本数。-refreshIntervall
:索引的刷新间隔。用于创建索引。默认值为“1s”。-indexStoreType
:索引的索引存储类型。用于创建索引。默认值为“1s”。-createIndex
: 标记是否在存储库引导时创建索引。默认值为true。-versionType
:版本管理的配置。默认值为外部。@Id
:应用于字段级别以标记用于标识目的的字段。@Transient
:默认情况下,所有字段在存储或检索时都映射到文档,此注释不包括该字段。@PersistenceConstructor
:标记一个给定的构造函数–甚至是一个包保护的构造函数–再从数据库中实例化对象时使用。构造函数参数按名称映射到检索到的Document中的键值。@Field
:应用于字段级别并定义字段的属性,大部分属性映射到各自的Elasticsearch Mapping定义(以下列表不完整,查看注释Javadoc以获得完整参考): -name
:将在 Elasticsearch 文档中表示的字段名称,如果未设置,则使用 Java 字段名称。-type
:字段类型,可以是Text、Keyword、Long、Integer、Short、Byte、Double、Float、Half_Float、Scaled_Float、Date、Date_Nanos、Boolean、Binary、Integer_Range、Float_Range、Long_Range、Double_Range、Date_Range、Ip_Range、Object 之一, 嵌套, Ip, TokenCount, Percolator, Flattened, Search_As_You_Type。-format
以及Date类型pattern
的定义。-store
: 标记原始字段值是否应该存储在 Elasticsearch 中,默认值为false。-analyzer
,searchAnalyzer
,normalizer
用于指定自定义分析器和规范器。@GeoPoint
: 将字段标记为geo_point数据类型。如果字段是类的实例,则可以省略GeoPoint
。
映射规则
类型
映射使用嵌入在发送到服务器的文档中的类型来允许泛型类型映射。这些类型_class在文档中表示为属性,并为每个聚合跟写入
publicclassPerson{@Id String id;
String firstname;
String lastname;}
{"_class":"com.example.Person","id":"cb7bef","firstname":"Sarah","lastname":"Connor"}
类型可以配置为保存自定义信息。使用
@TypeAlias
注释来执行此操作
带别名的类型
@TypeAlias("human")publicclassPerson{@Id String id;// ...}
{"_class":"human","id":...}
地理空间类型
Point
像&这样的地理空间类型
GeoPoint
被转换为纬度/经度对。
publicclassAddress{
String city, street;
Point location;}
{"city":"Los Angeles","street":"2800 East Observatory Road","location":{"lat":34.118347,"lon":-118.3026284}}
GeoJson类型
Spring Data Elasticsearch 通过为不同几何提供接口
GeoJson
和实现来支持 GeoJson 类型。它们根据 GeoJson 规范映射到 Elasticsearch 文档。实体的相应属性在索引映射中指定,就像
geo_shape
编写索引映射时一样。
publicclassAddress{
String city, street;
GeoJsonPoint location;}
{"city":"Los Angeles","street":"2800 East Observatory Road","location":{"type":"Point","coordinates":[-118.3026284,34.118347]}}
自定义转化
元模型对象映射配置
@ConfigurationpublicclassConfigextendsAbstractElasticsearchConfiguration{@Overridepublic RestHighLevelClient elasticsearchClient(){return RestClients.create(ClientConfiguration.create("localhost:9200")).rest();}@Bean@Overridepublic ElasticsearchCustomConversions elasticsearchCustomConversions(){returnnewElasticsearchCustomConversions(
Arrays.asList(newAddressToMap(),newMapToAddress()));}@WritingConverterstaticclassAddressToMapimplementsConverter<Address, Map<String, Object>>{@Overridepublic Map<String, Object>convert(Address source){
LinkedHashMap<String, Object> target =newLinkedHashMap<>();
target.put("ciudad", source.getCity());// ...return target;}}@ReadingConverterstaticclassMapToAddressimplementsConverter<Map<String, Object>, Address>{@Overridepublic Address convert(Map<String, Object> source){// ...return address;}}}
版权归原作者 低调小马(mcy) 所有, 如有侵权,请联系我们删除。