当前位置:   article > 正文

elasticsearch-基础知识-API-spring data集成_spring data elasticsearch使用normalizer

spring data elasticsearch使用normalizer

elasticsearch与关系数据库的对应
在这里插入图片描述
Elasticsearch集群可以包含多个索引(indices)(数据库),每一个索引可以包含多个类型(types)(表),每一个类型包含多个文档(documents)(行),然后每个文档包含多个字段(Fields)(列)。

完美解释:https://mp.weixin.qq.com/s/stC_xMP1n3aQ-0ZNAc3eQA

elasticsearch本地地址为:http://localhost:9200/

创建索引,类型,数据

使用PUT请求:访问地址/megacorp/employee/1
数据格式:
{
    "first_name" : "John",
    "last_name" :  "Smith",
    "age" :        25,
    "about" :      "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

返回数据

{
    "_index": "megacorp",
    "_type": "employee",
    "_id": "1",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "interests": [
            "sports",
            "music"
        ],
        "first_name": "sun"
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在这里插入图片描述

检索数据:

根据ID检索
GET http://localhost:9200/megacorp/employee/1
返回数据
{
    "_index": "megacorp",
    "_type": "employee",
    "_id": "1",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "first_name": "sun",
        "last_name": "sishuai",
        "age": 30,
        "about": "I like music,IT tech",
        "interests": [
            "sports",
            "music"
        ]
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
返回指定fields     _source
GET http://localhost:9200/megacorp/employee/1?_source=first_name,interests
  • 1
  • 2
返回所有文档_search
GET http://localhost:9200/megacorp/employee/_search
  • 1
  • 2
创建文档_create
如果有相同ID则创建失败,返回状态码409
PUT http://localhost:9200/megacorp/employee/1/_create
  • 1
  • 2
  • 3
创建文档
有相同ID则更新,没有则创建
PUT http://localhost:9200/megacorp/employee/1/
  • 1
  • 2
  • 3
删除:
DELETE  http://localhost:9200/megacorp/employee/5/
返回
{
    "_index": "megacorp",
    "_type": "employee",
    "_id": "5",
    "_version": 2,
    "result": "deleted",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 1,
    "_primary_term": 1
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
指定条件检索
_search?q=last_name:Smith
  • 1
  • 2

添加权限控制,设置访问密码:

需要在elasticsearch.yml中添加配置,启用x-pack

xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
  • 1
  • 2

总配置如下:

node.name: node1
cluster.name: clusters

bootstrap.system_call_filter: false
network.host: 0.0.0.0

http.cors.enabled: true
http.cors.allow-origin: '*'
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

重启elasticsearch
在这里插入图片描述
在bin下运行命令:elasticsearch-setup-passwords interactive
设置所有密码

访问方式:
使用postman在authorization中type选择Basic Auth,输入刚刚设置的用户名和密码,就可以使用以前的链接操作了

elastic集群之间信息传输(传输层TLS/SSL)加密:
https://www.elastic.co/guide/en/elasticsearch/reference/6.3/configuring-tls.html#tls-active-directory

Kibana连接监控elastic文档:
https://www.elastic.co/guide/en/kibana/6.8/connect-to-elasticsearch.html
kibana.yml配置:
连接elastic,登录密码和配置一样
管理员权限

elasticsearch.username: elastic
elasticsearch.password: elastic
  • 1
  • 2

这个权限小

elasticsearch.username: kibana
elasticsearch.password: kibana
  • 1
  • 2

Logstash
可以把 Logstash 理解成流入、流出 Elasticsearch 的传送带。

支持:不同类型的数据或实施数据流经过 Logstash 写入 ES 或者从 ES 中读出写入文件或对应的实施数据流。

参考:https://blog.csdn.net/choelea/article/details/80524518

JAVA开发:https://www.elastic.co/guide/en/elasticsearch/client/index.html

分为两个Java API和Java REST Client两种:据说Java API TransportClient即将过时,所以还是用Java REST Client吧

Java REST Client:Java低级REST客户端和Java高级REST客户端两种

开发代码参考:https://blog.csdn.net/aA518189/article/details/88956889

开发:

有两种实现方式:Java Client、Spring Data
其中Spring Data 包含JPA和elasticsearch两种方式
https://www.cnblogs.com/leeSmall/p/9218779.html

个人建议:JAVA Client网上资料很多,也是官方推荐,可以使用;Spring Data因为是Spring框架集成,如果用到Spring框架可以使用,我打算尝试Spring Data

spring集成elastic认证:https://stackoverflow.com/questions/42838459/connecting-to-xpack-enabled-elasticsearch-5-x-via-spring-data-elasticsearch/46016226#46016226

spring-data-elasticsearch GitHub源码:

:https://github.com/spring-projects/spring-data-elasticsearch
  • 1

官网:
有社区、博客等等

https://www.elastic.co/cn/
https://elasticsearch.cn/
  • 1
  • 2

关于API:

elasticsearch 自己的API,只是JSON形式的,搜索查询

用于练手elasticsearch 工具原生查询
https://www.elastic.co/guide/en/elasticsearch/reference/6.0/normalizer.html
  • 1
  • 2

Spring官方的关于Spring Data elasticsearch配置及使用文档,各种细节(都在超链接里),包含方法的命名等等

两个地址是一样的,一个是指定了3.1.10版本,另一个是最新版本
https://docs.spring.io/spring-data/elasticsearch/docs/3.1.10.RELEASE/reference/html/#elasticsearch.repositories
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/
  • 1
  • 2
  • 3

JAVA开发使用的API

JAVA版本的elasticsearch内核核心6.0.1 API版本
https://static.javadoc.io/org.elasticsearch/elasticsearch/6.0.1/overview-summary.html

Spring Data elasticsearch
https://docs.spring.io/spring-data/elasticsearch/docs/current/api/

elasticserach官方提供:
Java高级REST客户端--具体查询API:
https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-query-builders.html
Elasticsearch客户端API:
https://www.elastic.co/guide/en/elasticsearch/client/index.html

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

为什么spring配置的是9300端口,而我们请求的时候用的是9200

9200作为Http协议,主要用于外部通讯

9300作为Tcp协议,jar之间就是通过tcp协议通讯

ES集群之间是通过9300进行通讯
  • 1
  • 2
  • 3
  • 4
  • 5

spring-data-elasticsearch 3.1.10.RELEASE和3.0.8.RELEASE之间源码存在差异

@Bean
    public TransportClient transportClient() throws UnknownHostException {
        return new PreBuiltXPackTransportClient(Settings.builder()
                .put("cluster.name", "clusters")
                .put("xpack.security.user", "elastic:elastic")
                .build())
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

本段代码中的InetSocketTransportAddress存在于3.0.8,而3.1.10不存在


  • elastic启动报错:
[WARN ][o.e.t.OutboundHandler    ] [node1] send message failed [channel: 
Netty4TcpChannel{localAddress=0.0.0.0/0.0.0.0:55964, remoteAddress=/127.0.0.1:9300}]
javax.net.ssl.SSLException: Received fatal alert: handshake_failure
 at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) ~[?:?]
  • 1
  • 2
  • 3
  • 4

这个报错是因为开启了xpack安全验证导致的,xpack只有30天有效期,需要的话需要续费
在这里插入图片描述
避免报错需要将elasticsearch.yml相关配置xpack关闭(false)

xpack.security.enabled: false
xpack.security.transport.ssl.enabled: false
  • 1
  • 2
  • elasticsearch遇到的坑

首先要检查spring版本、elastic版本、以及spring data版本、还有其他各种版本

1.报错找不到org/springframework/core/ReactiveTypeDescriptor

org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document 
from file [D:\学习技术\shiro\shiro-example-master\shiroall\elastic-search\target\elastic-search\WEB-INF\classes\app-
elastic.xml]; nested exception is java.lang.NoClassDefFoundError: org/springframework/core/ReactiveTypeDescriptor
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.j
	ava:414)
	***
	***
	Caused by: java.lang.NoClassDefFoundError: org/springframework/core/ReactiveTypeDescriptorCaused by: java.lang.NoClassDefFoundError: org/springframework/core/ReactiveTypeDescriptor
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这是由于spring版本不匹配引起的,新版的elasticsearch一般都是对spring版本要求很高,因此我把我的spring从4.X升级到5.X,问题解决
https://stackoverflow.com/questions/51588873/java-lang-abstractmethoderror-with-spring-data-elasticsearch

pom.xml

<dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.1.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

估计可能是spring-data-elasticsearch等引起的版本不一致问题,,导致加载的时候旧版本中的spring没有相关的方法

2.java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/exc/InvalidDefinitionException
升级databind

 <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <!--<version>2.8.7</version>-->
            <version>2.9.5</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

由2.8.7升级2.9.5
3.Java ElasticSearch None of the configured nodes are available
xml配置elastic的时候,cluster-name属性是必不可少的
在这里插入图片描述

4.报错:nested exception is org.springframework.data.mapping.PropertyReferenceException: No property firstName found for type Employee! Did you mean ‘first_Name’?

这个问题是由于属性使用自定义方法名中含有下划线,但是PO中没有xxx.first.name属性,elasticsearch对于继承
ElasticsearchRepository的user Repository方法名解析下划线代表下划线前的表示引用,后面的表示属性(可能表达不
准确),如上述它会去PO中通过方法名findByFirst_Name去查找是否存在po.first.name属性,而不是po.first_name,因
此在elastic中最好不要出现带有下划线的属性,po中最好也不要用,要驼峰命名,**下面也有解释,和JAVA解决办法**
  • 1
  • 2
  • 3
  • 4

一般来说elastic命名有规则限制都是findByxxx,getByxxx等等,并且名字直接与实体类PO有关(一般都是相同),spring data elasticsearch根据方法名称自动生成查询语句,如果属性中存在下滑线,一般要改成驼峰命名,否则无法处理;属性带下滑线,当定义成方法名后,会被认为成是对象的属性,例如 List<Employee> findByFirst_name(String name);会被解析成Employee.first.name,而Employee对象只有first_name
参考:https://docs.spring.io/spring-data/elasticsearch/docs/3.1.10.RELEASE/reference/html/#repositories.query-methods.details
在这里插入图片描述
在这里插入图片描述

一般实现数据查询有两种JPA和spring data
JAP就是典型的JAVA提供的API进行查询,包括注解和XML方式,传统的hibernate就是JPA,里头有一套方法继承下来可以使用,注解会有@Table @Column @Entity;mybatis不是JPA,mybatis是另一套持久层框架

elasticsearch也有两种实现方式spring data JPA和spring data elasticsearch,
区别在于继承的Repository,如果是显示继承那么就是两者之一
在这里插入图片描述
如果没有显示继承,那么就看PO注解
在这里插入图片描述

5.由于版本原因查询语句变更
新版本:

SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(matchAllQuery())
                //参数firstName大小写都能查
                .withFilter(QueryBuilders.matchQuery(field,value))
                //参数firstName如果大写了查不到相应的数据
                //.withFilter(QueryBuilders.termQuery("first_name",firstName))
                .build();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

历史版本:

QueryBuilder boolQueryBuilder = boolQuery().should(matchQuery("skuCode", keyword)).
should(matchQuery("name", keyword));
FilterBuilder filterBuilder = boolFilter().must(termFilter("enabled", true), termFilter("type", "SIMPLE"), 
termFilter("tenantCode", "Triveni"));
NativeSearchQueryBuilder().withQuery(QueryBuilders.filteredQuery(boolQueryBuilder, filterBuilder).build();
  • 1
  • 2
  • 3
  • 4
  • 5

差别在于boolFilter()和withFilter()上

Spring Data Elasticsearch集成–简单举例

pom.xml

		<dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.1.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

elastic.xml

虽然配置了elasticsearchTemplate,如果用的是elasticsearch repositories不会用到,(例子中用到了)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/data/elasticsearch
        http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd ">

    <!-- 扫描DAO包 自动创建实现 -->
    <elasticsearch:repositories base-package="com.elastic.dao" />


    <!-- 配置elasticsearch 连接 -->
    <elasticsearch:transport-client id="client" cluster-nodes="localhost:9300" cluster-name="clusters"/>

    <!-- spring data elasticsearch DAO 必须依赖 elasticsearchTemplate  -->
    <bean id="elasticsearchTemplate"
          class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
        <constructor-arg name="client" ref="client" />
    </bean>

</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Repository(例子中是dao层)

package com.elastic.dao;

import com.elastic.po.Employee;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface NameQuery extends ElasticsearchRepository<Employee, String> {
    List<Employee> findByAge(String age);

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

PO
在这里插入图片描述
service

package com.elastic.service;

import com.elastic.po.Employee;

import java.util.List;

public interface NameQueryService {
    List<Employee> findByFirstName(String firstName);

    List<Employee> findByFirstNameFromQuery(String firstName);

    List<Employee> findByAge(String age);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

service-impl

package com.elastic.service.impl;

import com.elastic.dao.NameQuery;
import com.elastic.po.Employee;
import com.elastic.service.NameQueryService;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

import static org.elasticsearch.index.query.QueryBuilders.*;

@Service
public class NameQueryServiceImpl implements NameQueryService {

    @Autowired
    private NameQuery nameQuery;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;


    @Override
    public List<Employee> findByAge(String age) {
        List<Employee> emps = nameQuery.findByAge(age);
        return emps;
    }

    @Override
    public List<Employee> findByFirstName(String firstName) {

        List<Employee> emps = new ArrayList<Employee>();
        SearchQuery searchQuery = userSearchQuery("first_name",firstName);
        Page<Employee> empsPage = nameQuery.search(searchQuery);

        if(!empsPage.isEmpty()){
            emps = empsPage.getContent();
        }
        return emps;
    }
    public List<Employee> findByFirstNameFromQuery(String firstName){

        SearchQuery searchQuery = userSearchQuery("first_name",firstName);
        List<Employee> emps = elasticsearchTemplate.queryForList(searchQuery,Employee.class);
        return emps;
    }

    public SearchQuery userSearchQuery(String field,String value){
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(matchAllQuery())
                //参数firstName大小写都能查
                .withFilter(QueryBuilders.matchQuery(field,value))
                //参数firstName如果大写了查不到相应的数据
                //.withFilter(QueryBuilders.termQuery("first_name",firstName))
                .build();
        return searchQuery;
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

controller

package com.elastic.controller;

import com.elastic.po.Employee;
import com.elastic.service.NameQueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/nameQuery")
public class NameQueryController {

    @Autowired
    private NameQueryService nameQueryService;

    @RequestMapping("/findByFirstName.do")
    public List<Employee> findByFirstName(@RequestParam String firstName){
        return nameQueryService.findByFirstName(firstName);
    }
    @RequestMapping("/findByAge.do")
    public List<Employee> findByAge(@RequestParam String age){
        return nameQueryService.findByAge(age);
    }

    @RequestMapping("/findByFirstNameFromQuery.do")
    public List<Employee> findByFirstNameFromQuery(@RequestParam String firstName){
        return nameQueryService.findByFirstNameFromQuery(firstName);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

索引(例子):

{
        "_index": "megacorp",
        "_type": "employee",
        "_id": "2",
        "_score": 1.0,
        "_source": {
          "first_name": "John",
          "last_name": "smith",
          "age": 19,
          "about": "I like qiaqia",
          "interests": [
            "movie",
            "eat"
          ]
        }
      },
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "4",
        "_score": 1.0,
        "_source": {
          "first_name": "cc",
          "last_name": "smith",
          "age": 19,
          "about": "I like qiaqia",
          "interests": [
            "movie",
            "eat"
          ]
        }
      }
      }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

数据导入,增删改查,按score,权重进行匹配,spring data elasticsearch API

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/457575
推荐阅读
相关标签
  

闽ICP备14008679号