spring cloud 引入elasticsearch做oracle数据库全文检索(一)

本文详细介绍了如何在Spring Cloud项目中集成Elasticsearch,包括版本匹配、配置、实体映射、DAO层编写及常见错误处理。同时,深入探讨了查询语法、高级检索技巧及扩展应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

一、spring cloud 引入spring-boot-starter-data-elasticsearch

      1. spring cloud集成了elasticsearch,但是我们部署的elasticsearch版本要与引入的elasticsearch的jar版本一直

elasticsearch的版本引用之前文章中的elk搭建的版本

{

  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "6.8.3",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "0c48c0e",
    "build_date" : "2019-08-29T19:05:24.312154Z",
    "build_snapshot" : false,
    "lucene_version" : "7.7.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

 

引入pom

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

 

2.  配置文件配置

spring:  
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 192.168.12.122:9300
      repositories: 
        enabled: true

//切记这里是9300 不是9200.  9300是客户端连接的服务

     3.  与之前hibernate一样,elasticsearch也有mapping。给实体类添加注解。

     mapping是类似于数据库中的表结构定义,

            1)  对象添加@Document注解,可以设置indexName、type、useServerConfiguration、shards、replicas、refreshInterval、indexStoreType、createIndex

indexName,定义当前对象索引,该对象就是一个文档(数据库)

type,文档逻辑分类,(数据库表)

             2)  对象属性添加注解,@Field(type = FieldType.Keyword) 

//text,当字段被全文搜索,设置后内容会被分析成一个一个词项,不用于排序
//keyword,适用于索引结构化字段,设置后可以排序、精确过滤、聚合。只能精确搜索
字符串类型  text,keyword 
//数值类型,尽可能选择合适的,类型字段长度越短,索引和搜索效率越高
整数类型    integer,long, short, byte
浮点类型    double,float,half_float,scaled_float
逻辑类型    boolean
日期类型	    date
范围类型	    range
二进制类型	binary
数组类型	    array
对象类型	    object
嵌套类型	    nested
地理坐标类型	geo_point
地理地图    	geo_shape
IP类型	    ip
范围类型	    completion
令牌计数类型	token_count
附件类型	    attachment

       3)  analyer,指定分词器,可以自定义按什么分词,例如:analyzer = "whitespace"按空格分词

            standard分词器对一句中文进行分词,会分成一个字一个字。

             第三方analyer插件,中文分词ik分词器,比如:ik、pinyin等。例如:  analyzer = "ik_max_word",会把        

你好吗?我有一句话要对你说呀。分成,你好,好吗,我,有,一句话,一句,一,句话,句,话,要对,你,说呀

分词之后检索更加快捷。

实体类:

@Document(indexName = "release", type = "inter_info", shards = 1, replicas = 0)
public class ReleaseDataBean implements Serializable {
	
	private static final long serialVersionUID = 4454026607520652287L;
	@Field(type = FieldType.Keyword)
	private String id;
	// 数据包的表名
	private String dataSetTableName;
	// 发布接口的名称
	@Field(type = FieldType.Text, analyzer = "ik_max_word")
	private String name;
	// url类型
	@Field(type = FieldType.Text, analyzer = "ik_max_word")
	private String urlType;
	// 请求类型
	@Field(type = FieldType.Text, analyzer = "ik_max_word")
	private String requestType;
	// 操作人
	@Field(type = FieldType.Text, analyzer = "ik_max_word")
	private String operator;
	// 发布时间
	@Field(type = FieldType.Text, analyzer = "ik_max_word")
	private String releaseDate;
	// 数据包名称
	private String dataSetName;
	// 发布url
	private String url;
	// token验证
	private String token;

    4. 编写dao层,存取对象于elasticsearch

public interface ReleaseElasticRepository extends ElasticsearchRepository<ReleaseDataBean, Long> {

	@Query("{\"bool\" : {\"must\" : {\"field\" : {\"name\" : \"?\"}}}}")
	Page<ReleaseDataBean> findByName(String name, Pageable pageable);

}

  参考:https://blog.youkuaiyun.com/weixin_40790313/article/details/84529265

5. service

@Autowired
private ReleaseElasticRepository releaseElasticRepository;

@Autowired
private ElasticsearchTemplate elasticsearchTemplate;


@Override
public void saveElasticRelease(ReleaseDataBean releaseDataBean) {
	createIndex();
	releaseElasticRepository.save(releaseDataBean);
}

private void createIndex() {
	if(!elasticsearchTemplate.indexExists(ReleaseDataBean.class)) {
		elasticsearchTemplate.createIndex(ReleaseDataBean.class);
	}
}

番外:容易出错的点

1>  客户端连接端口是9300, 应用的端口是9200

2>  我们使用elk的docker打镜像,必须将9300端口发布出来

3>  使用analyzer = "ik_max_word"注解,也会报错因为没有引入插件

安装步骤,进入/opt/elasticsearch/plugins文件夹下。
mkdir ik
cd ik
//将插件zip放在该目录下,然后解压
unzip elasticsearch-analysis-ik-6.8.3.zip

//由于我们的是docker部署
将本地linux文件放到docker中
//宿主到docerk
docker cp 本地文件的路径 container_id:<docker容器内的路径>
docker cp  /myfiles/services_cq/docker/elasticsearch-analysis-ik-6.8.3.zip 49f6d0ec480f:/opt/elasticsearch/plugins/ik/elasticsearch-analysis-ik-6.8.3.zip
//docekr到宿主
docker cp container_id:<docker容器内的路径> <本地保存文件的路径>


 v5.5.1 之后
安装命令,不可以在plugins下面有ik文件夹
直接安装
cd /opt/elasticsearch/bin
//直接install
./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.8.3/elasticsearch-analysis-ik-6.8.3.zip

6. 保存之后查询

    

本身是这样的,编写查询规则

//远程调用
curl -XGET 'localhost:9200/index/type/_search?pretty' -d '
{
"query": { "match_all": {} },
"from":1,
"size":2
}'

//与上图匹配
GET index/type/_search
{
  "query": {
    "match_all": {}
  }
}

//可以查询多个index和type查询
GET release*/inter_info/_search
{
  "query": {
    "match_all": {}
  }
}

   番外二 :query查询语法

// query下一层级主要是说明搜索类型。以何种方式来检索。
match_all    查询全部   (相当于 select * from table)
match        模糊匹配   (相当于 select * from table where A like '%%')
例子:
"query": {
    "match": {
      "name": "接口"
    }
  }
match_phrase 全句匹配   (相当于 select * from table where A = B)
muti_match   多字段匹配 
query_string 语法查询    用于keyword,直接匹配关键字
term         字查询      为啥是字,因为所有存储的都分为单个字,如果是词则查不到。例如:成都,成,都,都可以查到,但是“成都”查不到
range        范围查询

// 分页,与query同级
from : 10,
size : 10

这里我重启了elasticsearch,发现数据依然在,也就是说该是永久存储在硬盘中的。

 

elasticsearch引入项目的扩展应用。

1.支持原生的es api查询

SearchQuery searchQuery = new NativeSearchQueryBuilder()
  .withQuery(matchAllQuery())
  .withFilter(boolFilter().must(termFilter("id", documentId)))
  .build();
 
Page<SampleEntity> sampleEntities =
  elasticsearchTemplate.queryForPage(searchQuery,SampleEntity.class);

2.使用Scan和Scroll进行大结果集查询

SearchQuery searchQuery = new NativeSearchQueryBuilder()
  .withQuery(matchAllQuery())
  .withIndices("test-index")
  .withTypes("test-type")
  .withPageable(new PageRequest(0,1))
  .build();
String scrollId = elasticsearchTemplate.scan(searchQuery,1000,false);
List<SampleEntity> sampleEntities = new ArrayList<SampleEntity>();
boolean hasRecords = true;
while (hasRecords){
  Page<SampleEntity> page = elasticsearchTemplate.scroll(scrollId, 5000L , new ResultsMapper<SampleEntity>()
  {
    @Override
    public Page<SampleEntity> mapResults(SearchResponse response) {
      List<SampleEntity> chunk = new ArrayList<SampleEntity>();
      for(SearchHit searchHit : response.getHits()){
        if(response.getHits().getHits().length <= 0) {
          return null;
        }
        SampleEntity user = new SampleEntity();
        user.setId(searchHit.getId());
        user.setMessage((String)searchHit.getSource().get("message"));
        chunk.add(user);
      }
      return new PageImpl<SampleEntity>(chunk);
    }
  });
  if(page != null) {
    sampleEntities.addAll(page.getContent());
    hasRecords = page.hasNextPage();
  }
  else{
    hasRecords = false;
  }
  }
}

3.获取client实例进行节点操作,可以自行封装Util方法,client包含节点的所有信息,以及针对请求 或者返回值做处理

 

4. 从多个索引中检索

     基础版:

SearchResponse response = elasticsearchTemplate.getClient().prepareSearch("index1", "index2")
				.setTypes("type1", "type2").setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
				.setQuery(QueryBuilders.termQuery("name", name)) // Query
				.setPostFilter(QueryBuilders.rangeQuery("age").from(12).to(18)) // Filter
				.setFrom(0).setSize(60).setExplain(true).get();

return response.toString();

     进阶版:

public List<ReleaseDataBean> querBigEsObj(String name) {
		QueryBuilder queryBuilder = QueryBuilders.matchPhrasePrefixQuery("name", name);
		QueryBuilder builder = QueryBuilders.indicesQuery(queryBuilder, "release");

		SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build();

		return elasticsearchTemplate.query(searchQuery, resultsExtractor -> {
			SearchHits hits = resultsExtractor.getHits();
			List<ReleaseDataBean> result = new ArrayList<>();
			Arrays.stream(hits.getHits()).forEach(h -> {
				Map<String, Object> source = h.getSource();
				ReleaseDataBean obj = new ReleaseDataBean();
				obj.setId(String.valueOf(source.getOrDefault("id", null)));
				result.add(obj);
			});
			return result;
		});
	}

 

1 term query 分词精确查询
QueryBuilder queryBuilder = QueryBuilders.termQuery("name", "华为手机");

2 terms Query 多term查询
QueryBuilder queryBuilder = QueryBuilders.termsQuery("name", "华为手机","摄像机");

3 range query 范围查询
QueryBuilder queryBuilder=QueryBuilders.rangeQuery("price").gte(5000).lt(10000);

4 exist query 查询字段不为null的文档
QueryBuilder queryBuilder= QueryBuilders.existsQuery("introduce");

5 prefix query 匹配分词前缀 如果字段没分词,就匹配整个字段前缀
QueryBuilder queryBuilder=QueryBuilders.prefixQuery("name","华");

6 wildcard query 通配符查询,支持* 任意字符串;?任意一个字符
QueryBuilder queryBuilder=QueryBuilders.wildcardQuery("name","华*");
QueryBuilder queryBuilder=QueryBuilders.wildcardQuery("name","ctr?")

7 regexp query 正则表达式匹配分词,正则表达式自己写吧
QueryBuilder queryBuilder=QueryBuilders.regexpQuery("name","华.*");

8 fuzzy query 分词模糊查询,通过增加fuzziness 模糊属性,来查询term 如下能够匹配 name 为 耳 耳前或后加一个字母的term的 文档 fuzziness 的含义是检索的term 前后增加或减少n个单词的匹配查询,
    QueryBuilder queryBuilder=QueryBuilders.fuzzyQuery("name","耳").fuzziness(Fuzziness.ONE);
9 type Query 查询某个type的数据
QueryBuilder queryBuilder=QueryBuilders.typeQuery("digital");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值