前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Elasticearch 搜索引擎(2: Java 整合Boot

Elasticearch 搜索引擎(2: Java 整合Boot

作者头像
Java_慈祥
发布2024-08-06 15:09:56
1650
发布2024-08-06 15:09:56
举报
文章被收录于专栏:Web前后端、全栈出发

承接上文: Elasticearch 搜索引擎

Boot 整合 Elasticearch

  • 普普通通来个Boot 工程:集成Elasticearch
  • 依赖,配置,各种api对象操作使用!

Elasticearch依赖配置:

pom.xml

代码语言:javascript
复制
    <dependencies>
<!-- Elasticsearch高级客户端。内部提供api 方法可以直接完成一些 http请求的调用,只需要输入对应参数即可,内部自动完成 -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>6.5.4</version>
        </dependency>
<!-- Elasticsearch 的依赖jar -->
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>6.5.4</version>  				<!-- 版本! -->
        </dependency>
    </dependencies>

配置文件 .yml

application.yml

代码语言:javascript
复制
#yml 配置定义自己的Elasticearch 启动服务运行端口;
my:
  es:
    host: 127.0.0.1:9200	#集群环境可以使用 ,xxx.x.x.x:9200,xxx.x.x.x:9200 来表示;

Elasticearch的配置类:

  • 对Elasticearch 集群ip端口的控制:

EsConfig

代码语言:javascript
复制
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EsConfig {

    @Value("${my.es.host}")       //@Value() 获取.yml 中配置后面方便,集群操作!
    private String hostList;


    @Bean                        //创建RESTful 的请求客户端对象, @Bean注入到SPring容器中!
    public RestHighLevelClient client() {
        //拆分hostList 逗号, 获得集群的ip集群数组!
        String[] hostStr = hostList.split(",");
        //创建HttpHost数组,其中存放es主机和端口的配置信息
        HttpHost[] httpHosts = new HttpHost[hostStr.length];
        //循环遍历: 0获取第一参数ip   1第二个参数 端口!
        for (int i = 0; i < hostStr.length; i++) {
            String str = hostStr[i];
            httpHosts[i] = new HttpHost(str.split(":")[0], Integer.parseInt(str.split(":")[1]), "http");
        }
        //存放在RestHighLevelClient,管理集群的ip 端口;
        return new RestHighLevelClient(RestClient.builder(httpHosts));
    }
}

主程序类:

TestRun.Java

代码语言:javascript
复制
import com.wsm.service.EsService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication 	//Boot的启动注解
public class TestRun {
    public static void main(String[] args) throws Exception {
    	//Boot,启动入口
        ConfigurableApplicationContext run = SpringApplication.run(TestRun.class, args);
        
        //通过run 起运行对象,获取到Spring容器中的对象!必须使用run来获取,不然直接new 会null pointer!
        //EsService 来源于Service层的实际代码操作!
        EsService es  = run.getBean(EsService.class); 	
        es.deleteIndex(); 	//删除索引库!
    }
}

正片开始:EsService

上面只是基本的环境搭建的简单配置, 下面才是Elasticearch 的关键代码部分:

基本,增删改 案例:


删除索引库

  • Delete 请求: http://localhost:9200/索引 直接删除索引

EsService.Java

代码语言:javascript
复制
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;

@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;
    
    //删除索引请求
    public void deleteIndex() throws Exception {
        //DeleteIndexRequest()方法参数: 要删除的索引名,返回一个删除索引请求对象;
        DeleteIndexRequest request = new DeleteIndexRequest("wsm");
        //client的方法执行删除,参数: 删除索引请求对象 RequestOptions.DEFAULT   返回一个Response响应对象;
        AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
        //返回结果true/false 失败/成功!
        System.out.println(delete.isAcknowledged());
    }
}
主程序测试:
  • 控制台返回:true/false

创建索引库/映射

6.0之后一个索引对应一个映射so: 建索引同时加映射;

  • 创建索引库put请求 http://localhost:9200/索引库名称 需要设置分片/配置
  • 创建映射 post http://localhost:9200/索引库名称/映射名称(类型,表)/_mapping 指定映射名,JSON的所需参数

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;
    
    //创建索引库,6.0之后一个索引对应一个映射so: 建索引同时加映射;
    public void createIndex() throws Exception {
        //创建索引请求对象————指定索引名
        CreateIndexRequest request = new CreateIndexRequest("wsm");
        //指定分片/备份
        request.settings(Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0"));
        //设置映射————类型名,fieid及属性类型...,JSON形式传输
        request.mapping("doc", "{\n" +
                "\t\"properties\": {\n" +
                "\t\t\"description\": {\n" +
                "\t\t\t\"type\": \"text\",\n" +
                "\t\t\t\"analyzer\": \"ik_max_word\",\n" +
                "\t\t\t\"search_analyzer\": \"ik_smart\"\n" +
                "\t\t},\n" +
                "\t\t\"name\": {\n" +
                "\t\t\t\"type\": \"text\",\n" +
                "\t\t\t\"analyzer\": \"ik_max_word\",\n" +
                "\t\t\t\"search_analyzer\": \"ik_smart\"\n" +
                "\t\t},\n" +
                "\t\t\"pic\": {\n" +
                "\t\t\t\"type\": \"text\",\n" +
                "\t\t\t\"index\": false\n" +
                "\t\t},\n" +
                "\t\t\"price\": {\n" +
                "\t\t\t\"type\": \"float\"\n" +
                "\t\t},\n" +
                "\t\t\"studymodel\": {\n" +
                "\t\t\t\"type\": \"keyword\"\n" +
                "\t\t},\n" +
                "\t\t\"timestamp\": {\n" +
                "\t\t\t\"type\": \"date\",\n" +
                "\t\t\t\"format\": \"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd\"\n" +
                "\t\t}\n" +
                "\t}\n" +
                "}", XContentType.JSON);
        //clientindices().create执行创建!—————— 请求参数,DEFAULT.
        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        //获取创建结果:boolean
        boolean acknowledged = createIndexResponse.isAcknowledged();
        System.out.println(acknowledged);
    }
}
主程序测试:
  • 控制台返回:truePostaman get查看创建成功!

添加文档 / 根据id修改文档

  • post 或 put 请求: http://localhost:9200/索引名/映射名/id值 传入JSON 参数形式,赋值生成一个Document 如果不指定id值ES会自动生成一个唯一ID 添加后的文档,再次执行,指定id 就可以直接修改数据了!

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;
    
    //新增文档! 添加数据!
    public void addDoc() throws Exception {
        //创建一个map类型存储要存储的数据,准备json数据
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("name", "spring cloud实战");
        jsonMap.put("description", "本课程主要从四个章节进行讲解: 1.微服务架构入门 2.spring cloud基础入门 3.实战Spring Boot 4.注册中心eureka。");
        jsonMap.put("studymodel", "201001");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        jsonMap.put("timestamp", dateFormat.format(new Date()));
        jsonMap.put("price", 5.6f);
        //索引请求对象————索引名,映射名,id(这里没有添加,相同的id会修改覆盖之前的文档数据!)
        IndexRequest request = new IndexRequest("wsm", "doc");
        //索引请求对象:内部会转换成JSON
        request.source(jsonMap); //存储参数数据,Object类型,这里是Map
        //索引响应对象
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        //获取响应结果
        DocWriteResponse.Result result = response.getResult();
        System.out.println(result);
    }
}
主程序测试:
  • Get请求: http://localhost:9200/索引名/映射名/id值http://localhost:9200/索引名/映射名/_search 查询所有数据!
  • id, 不指定默认提供!

id 查看文档数据

  • Get请求: http://localhost:9200/索引名/映射名/id值

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    //根据 id查询文档数据!
    public void getInfo() throws Exception {
        //根据索引名,文档名,id值: 获取文档数据
        GetRequest request = new GetRequest("wsm", "doc", "W8Q3FngBedCFzRwGU3V0");
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        System.out.println(response.isExists());                        //isExists() 响应中是否存在数据!
        Map<String, Object> sourceAsMap = response.getSourceAsMap();    //返回Map对象,直接输出打印
        System.out.println(sourceAsMap);
    }
}
主程序测试:
  • 控制台输出数据!

更新文档值

  • post请求: http://localhost:9200/索引名/映射/修改文档id/_update
代码语言:javascript
复制
{
   "doc" : {
      "修改Fieid" : "修改值..."
   }
}
  • 修改成功:_version版本+1;

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    //更新文档
    public void update() throws Exception {
        //指定 索引 映射 更新_id
        UpdateRequest request = new UpdateRequest("wsm", "doc", "XcRgFngBedCFzRwGanV-");
        //要更新的值
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("name", "spring boot实战");
        //要更新的值存入请求对象中;
        request.doc(jsonMap);
        //更新
        UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
        System.out.println(update.status());
    }
}
主程序测试:
  • 控制台不报错,返回ok
  • Postman get查看数据:
  • 值更改!中间出了个意味,重新增了个数据id 重新生成了

常用查询案例:

前言:

  • 搜索引擎最关键的就是要搜索结果,因此要有强大的查询能力!
  • 为了方便操作,学习,下面一个操作案例资源:
准备环境
  • 创建xc_course索引库 Put请求 http://localhost:9200/xc_course 别忘了分片/备份;
  • 创建映射 Post http://localhost:9200/xc_course/doc/_mapping

映射的 JSON数据

代码语言:javascript
复制
{
	"properties": {
		"description": {
			"type": "text",
			"analyzer": "ik_max_word",
			"search_analyzer": "ik_smart"
		},
		"name": {
			"type": "text",
			"analyzer": "ik_max_word",
			"search_analyzer": "ik_smart"
		},
		"pic": {
			"type": "text",
			"index": false
		},
		"price": {
			"type": "float"
		},
		"studymodel": {
			"type": "keyword"
		},
		"timestamp": {
			"type": "date",
			"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
		}
	}
}

插入数据:post/put

代码语言:javascript
复制
http://localhost:9200/xc_course/doc/1 
{
	"name": "Bootstrap开发",
	"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,是一个非常流行的开发框架,此框架集成了 多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松 的实现一个不受浏览器限制的精美界面效果。",
	"studymodel": "201002",
	"price": 68.6,
	"timestamp": "2018-04-25 19:11:35",
	"pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}
http://localhost:9200/xc_course/doc/2 
{
	"name": "java编程基础",
	"description": "java语言是世界第一编程语言,在软件开发领域使用人数最多。",
	"studymodel": "201002",
	"price": 68.6,
	"timestamp": "2018-04-25 19:11:35",
	"pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}
http://localhost:9200/xc_course/doc/3 
{
	"name": "spring开发基础",
	"description": "spring 在java领域非常流行,java程序员都在用。",
	"studymodel": "201001",
	"price": 88.6,
	"timestamp": "2018-04-25 19:11:35",
	"pic": "group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

查询所有文档

  • Get请求 http://localhost:9200/xc_course/doc/_search
  • Post请求: http://localhost:9200/xc_course/doc/_search

Post JSON数据

代码语言:javascript
复制
//post 请求,可以加入很多的条件...实现:分页,条件,多条件...等高级查询;
{ 
	"query": { 
	"match_all": {} 
	}
} 

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    //查询全部数据
    public void testSearchAll ()throws Exception{
        //SearchRequest用于与搜索文档、聚合、定制查询有关的任何操作,还提供了在查询结果的基于上,对于匹配的关键词进行突出显示的方法。
        SearchRequest searchRequest = new SearchRequest("xc_course"); //指定查询的索引
        searchRequest.types("doc");  //指定查询的 映射;
        //执行查询的构造对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //指定查询的方式;
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //Source源字段的过滤,指定查询的fieid,相当于: select 列1,列2... 指定查询的列;
        searchSourceBuilder.fetchSource(new String[]{"name","description"}, new String[]{});
        //完善请求数据:传入构造对象;
        searchRequest.source(searchSourceBuilder);

        // client发送请求! 获取响应数据Response
        SearchResponse searchResponse = client.search(searchRequest , RequestOptions.DEFAULT);
        //获取到hits 属性属性
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        //循环遍历数组,渠道数据!打印输出!全部数据!
        System.out.println(searchHits);
        for (SearchHit hit : searchHits) {
            System.out.println(hit.getIndex());
            System.out.println(hit.getId());
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            String studymodel = (String) sourceAsMap.get("description");
            System.out.println(name + "\t" + studymodel + "\t" + sourceAsMap);
        }
    };
}
主程序测试:
  • 结果只有 name description
  • 感谢大佬总结的图文资料:

分页查询

  • post请求: http://localhost:9200/xc_course/doc/_search

JSON参数

代码语言:javascript
复制
{
	"from": 0,	//起始文档的下标,从0开始.
	"size": 1,	//查询的文档数量	
	"query": {
		"match_all": {}
	},
	"_source": ["name", "studymodel"]	//指定查询fieid
}
  • from size _source 与query同级!

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;


    //分页查询数据
    public void queryPage() throws Exception {
        SearchRequest request = new SearchRequest("xc_course");
        request.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //设置
        int index = 1;
        int size = 2;
        searchSourceBuilder.from((index - 1) * size);   //设置起始位置
        searchSourceBuilder.size(size);                 //设置查询的个数!
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        
        searchSourceBuilder.fetchSource(new String[]{"name", "studymodel"}, new String[]{});
        //包装完整的请求对象
        request.source(searchSourceBuilder);
        //发起请求获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        //省略输出数据!
        
    }
 }

精准Term 查询 Query

  • 在搜索时,不会进行关键词拆分整体进入数据库查询 精准查询
  • post请求: http://localhost:9200/xc_course/doc/_search
代码语言:javascript
复制
{	
	"query": {
		//term:设置精准查询;
		"term": {              
			"name": "java"  //name 精确值Java相当于: like %_% 但值必须得是,分词表的值;     
		}
	}
}

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    //精准查询
    public void termAll() throws Exception {
        SearchRequest request = new SearchRequest("xc_course");
        request.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //指定查询的方式termQuery 精准查询参数
        //注意QueryBuilders.termQuery 只支持单参精确查;
        searchSourceBuilder.query(QueryBuilders.termQuery("studymodel", "201001"));
        //包装完整的请求对象
        request.source(searchSourceBuilder);
        //发起请求获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        //省略输出代码...
        
    }
}

根据id精确匹配

  • post请求: http://localhost:9200/xc_course/doc/_search
代码语言:javascript
复制
{
	"query": {
        //ids 设置id 请求查询...
		"ids": {
			"type": "doc",  //指定映射类型
			"values": "1"   //查询id 的值,可以使用 ["1", "2", "3"] 多选条件查,类似于in [] 
		}
	}
}

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;
    /*in查询*/
    public void inSearch() throws Exception {
        SearchRequest request = new SearchRequest("xc_course");
        request.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //设置ids,in []条件
        String[] ids = {"2", "3"};
        //指定查询的方式
        searchSourceBuilder.query(QueryBuilders.termsQuery("_id", ids));
        //包装完整的请求对象
        request.source(searchSourceBuilder);
        //发起请求获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
         //省略输出代码...
        
    }
}

分词match查询 Query + minimum_should_match占比查:

  • post请求: http://localhost:9200/xc_course/doc/_search
代码语言:javascript
复制
{
	"query": {
		//match:分词规则
		"match": {
			//某个fieid的查询分词...
			"description": {
				"query": "spring框架",	//搜索查询的参数,对其进行拆分,去与文档进行匹配!
				"operator": "or",		//or:拆分的词只要有一个成立就符合条件  and:拆分词都在文档中出现则才符合条件`精确查询`
                "minimum_should_match": "80%"
                //,"minimum_should_match": "80%": minimum_should_match指定文档匹配分词占比%
                //operator=or表示只要有一个词匹配上就得分, 实现三个词至少有两个词匹配如何实现:
                //"minimum_should_match": "80%"表示: 3个词在文档的匹配占比为80%: 3*0.8=2.4 ≈2;(至少有两个词在文档中要匹配成功)
			}
		}
	}
}
  • 页面输出,spring框架, Elasticearch将其进行拆分, Spring 框架
  • or 只要查询文档中匹配一个分词就符合条件,and 查询文档中词都要匹配才符合条件;

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    /*分词查询*/
    public void matchSearch() throws Exception {
        SearchRequest request = new SearchRequest("xc_course");
        request.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //指定查询的方式,不需要设置% 直接不.即可!
        searchSourceBuilder.query(QueryBuilders.matchQuery("description", "spring开发框架").operator(Operator.OR).minimumShouldMatch("80%"));
        //包装完整的请求对象
        request.source(searchSourceBuilder);
        //发起请求获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        //省略....
        
    }
}

多Fieid分词查:

  • 普通的分词查询只支持,单个Fieid 的分词查询,multiQuery支持多个Fieid的分词查询
  • 对搜索参数进行拆分, 与多个Fieid 进行分词匹配, 还可以通过 boots来划分分词Fieid的权重
  • post请求: http://localhost:9200/xc_course/doc/_search
代码语言:javascript
复制
{
	"query": {
		//多Fieid分词查规则;
		"multi_match": {
			//搜索框....
			"query": "spring框架",
			"minimum_should_match": "50%",
			//指定的多个 Fieid, ^设置权重;
			"fields": ["name", "description^10"]    
		}
	}
}

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    //多字段分词查询
    public void mutilMatchSearch() throws Exception {
        SearchRequest request = new SearchRequest("xc_course");
        request.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //指定查询的方式: 搜索数据 多个Fieid  or  80%  name列设置权重10
        searchSourceBuilder.query(QueryBuilders.multiMatchQuery("spring css", "description", "name").operator(Operator.OR).minimumShouldMatch("80%").field("name", 10));
        //包装完整的请求对象
        request.source(searchSourceBuilder);
        //发起请求获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        //省略....
        
    }
}

boolean查询,多条件查询:

  • post请求: http://localhost:9200/xc_course/doc/_search
  • must 表示必须,多个查询条件必须都满足.
  • should 表示或者,多个查询条件只要有一个满足即可
  • must_not 表示非
代码语言:javascript
复制
{
	"query": {
        //bool:实现多条件查;
		"bool": {
            //must: bool的多条件规则,另外还有:should must_no; (数组内部可以防止多个条件的规则)
			"must": [{
                //多列的分词查询
				"multi_match": {
					"query": "spring框架",
					"minimum_should_match": "50%",
					"fields": ["name^10", "description"]
				}
			}, {
                //精准查询规则
				"term": {
					"studymodel": "201002"
				}
			}]
		}
	}
}
  • 省略更多…需要深入发掘!

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    //Bool多条件查询
    public void boolSearch() throws Exception {
        SearchRequest request = new SearchRequest("xc_course");
        request.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //设置多字段的分词查询对象
        MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架", "description", "name").operator(Operator.OR).minimumShouldMatch("80%").field("name", 10);
        //设置精准查询对象
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");
        //创建多条件对象,并将规则条件传入bool中
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(matchQueryBuilder);
        boolQueryBuilder.must(termQueryBuilder);
        //指定查询的方式
        searchSourceBuilder.query(boolQueryBuilder);
        //指定查询的Fieid
        searchSourceBuilder.fetchSource(new String[]{"name", "studymodel", "description"}, new String[]{});
        //包装完整的请求对象
        request.source(searchSourceBuilder);
        //发起请求获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        //....
        
    }
}

过虑器 filter + 范围查 range

  • post请求: http://localhost:9200/xc_course/doc/_search
  • 过虑查: 是针对搜索的结果进行过虑,所以首先要有一个条件查询之后的结果集 对结果集进行的二次查询判断; 因为Filter的过滤操作是在 内存中完成的 相比Elasticearch 更快
  • range 范围查 范围过虑,保留大于等于 x 并且小于等于 y 的记录。 注意: range和term一次只能对一个Field设置范围过虑 多个就创建多个, range | term
代码语言:javascript
复制
{
	"_source": ["name", "studymodel", "description", "price"],
	"query": {
		"bool": {
			"must": [{
                //多列的分词查询,查询后的条件给过滤,进行内存条件判断;
				"multi_match": {
					"query": "spring框架",
					"minimum_should_match": "50%",
					"fields": ["name^10", "description"]
				}
			}],
            //过滤规则数组
			"filter": [{
                //详细过滤: studymodel列的精确值过滤;
				"term": {
					"studymodel": "201001"
				}
			}, {
                //范围查:   price范围过滤查  77 
				"range": {
					"price": {
						"gte": 60,  //大于等于
						"lte": 100  //小于等于
					}
				}
			}]
		}
	}
}

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;
   
   /*过滤条件查询*/
    public void filterSearch() throws Exception {
         SearchRequest request = new SearchRequest("xc_course");
        request.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //多字段的分词查询
        MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架", "description", "name").operator(Operator.OR).minimumShouldMatch("80%").field("name", 10);
        //精准查询
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");
        //范围查询
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price").gte(60).lte(100);
        //创建多条件对象
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(matchQueryBuilder);
        boolQueryBuilder.filter(termQueryBuilder);
        boolQueryBuilder.filter(rangeQueryBuilder);
        //指定查询的方式
        searchSourceBuilder.query(boolQueryBuilder);
        //包装完整的请求对象
        request.source(searchSourceBuilder);

        //发起请求获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        System.out.println(searchHits.totalHits);
        SearchHit[] hits = searchHits.getHits();
         //...
    }
}

排序

  • post请求: http://localhost:9200/xc_course/doc/_search
代码语言:javascript
复制
{
	"query": {
		"match_all": {} 
	},
    //排序规则数组:内部可以指定多列进行排序; (同级!)
	"sort": [{
		"studymodel": "desc"    //升序
	}, {
		"price": "asc"          //降序
	}]
}

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    //排序查询
    public void orderSearch() throws Exception {
        SearchRequest request = new SearchRequest("xc_course");
        request.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //设置排序规则
        searchSourceBuilder.sort(new FieldSortBuilder("studymodel").order(SortOrder.DESC));
        searchSourceBuilder.sort(new FieldSortBuilder("price").order(SortOrder.ASC));
        //包装完整的请求对象
        request.source(searchSourceBuilder);
        //发起请求获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        SearchHits searchHits = response.getHits();
        //...
    }
}

高亮显示

  • 高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。 搭配分词使用, 使分词查看的数据,突出显示
  • post请求: http://localhost:9200/xc_course/doc/_search
代码语言:javascript
复制
{
	"query": {
		"bool": {
			"must": [{
				"multi_match": {
					"query": "开发框架",
					"minimum_should_match": "50%",
					"fields": ["name^10", "description"],
					"type": "best_fields"
				}
			}]
		}
	},
    //高亮显示规则,搭配分词使用:
	"highlight": {
        //设置分词数据的前缀
		"pre_tags": ["<span style=’color:red;’>"],
        //设置分词数据的后缀
		"post_tags": ["</span>"],
        //要进行高亮的 fieid列...
		"fields": {
			"name": {},
			"description": {}
		}
	}
}

EsService.Java

代码语言:javascript
复制
@Service
public class EsService {
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    //高亮查询查询
    public void highlightSearch() throws Exception {
        SearchRequest request = new SearchRequest("xc_course");
        request.types("doc");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //多字段的分词查询
        MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery("spring框架", "description", "name").operator(Operator.OR).minimumShouldMatch("80%").field("name", 10);
        //创建多条件对象
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(matchQueryBuilder);
        //指定查询规则
        searchSourceBuilder.query(boolQueryBuilder);
        //配置高亮: 分词前缀,后缀,
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<span style='color;red;'>");
        highlightBuilder.postTags("</span>");
        highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
        highlightBuilder.fields().add(new HighlightBuilder.Field("description"));
        searchSourceBuilder.highlighter(highlightBuilder);
        //包装完整的请求对象
        request.source(searchSourceBuilder);
        //发起请求获取响应
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //....
        SearchHits searchHits = response.getHits();     //第一个hits
        SearchHit[] hits = searchHits.getHits();        //第二个hits数组,遍历;
        for (SearchHit hit : hits) {
            //获取原始数据输出....
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");     //获取源数据的name
            //获取高亮对象,数据输出...
            Map<String, HighlightField> fields = hit.getHighlightFields();
            if (fields != null) {
                HighlightField nameField = fields.get("name");  //获取name值返回,HighlightField ————>转换成Text数组
                if(nameField==null){    //非空判断!
                    continue;			//退出本次循环;
                }
                Text[] nameTxt = nameField.fragments();
                StringBuffer nameSbf = new StringBuffer();
                for (Text text : nameTxt) {
                    nameSbf.append(text.toString());
                }
                name = nameSbf.toString();
                System.out.println("------------------------------");
            }
            String studymodel = (String) sourceAsMap.get("description");
            System.out.println(name + "\t" + studymodel + "\t" + sourceAsMap);
    }
}
测试:

分组:

  • 向关系型数据库一样:Elasticearch也支持分组,指定某列进行分组… 获取某一个的各个唯一值:
  • Select 分组列 From 表 order by 分组列 desc/asc;

实例代码.Java

代码语言:javascript
复制
    @Autowired
    //RestHighLevelClien REST高级客户端对象,并自动映射配置类中的对象;
    private RestHighLevelClient client;

    //分组
    @GetMapping("/order")
    public   List<String>order() throws Exception {
        //指定:索引/映射
        SearchRequest request = new SearchRequest("wsm");
        request.types("houst");
        //创建构造对象;
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //构建设置分组: 设置分组别名——分组列——指定获取分组结果集数量;
        searchSourceBuilder.aggregation(AggregationBuilders.terms("typeidGroup").field("typeid").size(2));
        //放入请求中去!
        request.source(searchSourceBuilder);
        //请求
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        //获取分组数据
        Terms categoryGroup = search.getAggregations().get("typeidGroup");  //与别名对应,返回分组的数据;!
        //处理分组后的数据;
        List<String> cateList = termsAsList(categoryGroup);
        return cateList;
    }

    //遍历分组数据——获取List<String>集合
    public List<String> termsAsList(Terms terms) {
        List<String> list = new ArrayList<>();
        //遍历分组数据:
        for (int i = 0; i < terms.getBuckets().size(); i++) {
            //获取单个分组数据,存进list中;
            String str = terms.getBuckets().get(i).getKey().toString();
            list.add(str);
        }
        return list;
    }
  • 当然分组,还可以搭配其它条件进行分组。对条件判断之后返回的结果集进行 分组处理
常用场景:
  • 京东商品的,品牌/类型/spec规格:
  • 因为商品的数量/种类/规格/款式 是非常多的而且,不停更新的所以,商城商品页面的数据都是灵活多变,的数据库数据!
  • 可以通过分组,给商品进行分组,品牌进行分组…就可以获取不同商品的多个不同的品牌… 如果是箱子,根据箱子进行查询,分组品牌即可获得所有的箱子匹配进行动态的数据展示!
  • 规格:请借鉴下面代码:

分组JSON数据处理:

代码语言:javascript
复制
    //分组查询: 的数据是唯一的...
    //返回类型: 基于,Map: key唯一,set数据也是唯一的!
    public Map<String, Set> termsAdMap(Terms terms) {

        Map<String, Set> specMap = new HashMap<>();

        Set<String> specSet = new HashSet<>();
        //循环每一条分组之后的集合数据!存入set中,确保了存入的JSON是唯一的... (因为分组数据本就是唯一的,这个可以省略,但为了方便下面的循环遍历...)
        for (int i = 0; i < terms.getBuckets().size(); i++) {
            String str = terms.getBuckets().get(i).getKeyAsString();
            specSet.add(str);
        }
        //遍历set
        for (String specStr : specSet) {
            //将一个个JSON转换成Map对象,      {'颜色': '红色', '版本': '8GB+128GB'}————————>Map等于: key value
            Map<String, String> map = JSON.parseObject(specStr, Map.class);
            //遍历map
            for (Map.Entry<String, String> entry : map.entrySet()) {    //第一次循环↓↓↓
                //获取key value
                String key = entry.getKey();        //颜色
                String value = entry.getValue();    //红色

                //获取集合中是否存储规格: 颜色,没有就创建一个;
                Set set = specMap.get(key);
                if (set == null) {
                    set = new HashSet();
                }
                set.add(value);                     //将值增进行,如果红色已经存在, set 后面覆盖前面!
                //将新的规格数据,添加至 specMap
                specMap.put(key, set);
            }
        }
        return specMap;
    }
  • 实现:
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 承接上文: Elasticearch 搜索引擎
  • Boot 整合 Elasticearch
    • Elasticearch依赖配置:
      • 配置文件 .yml
        • Elasticearch的配置类:
          • 主程序类:
          • 正片开始:EsService
          • 基本,增删改 案例:
            • 删除索引库
              • 主程序测试:
            • 创建索引库/映射
              • 主程序测试:
            • 添加文档 / 根据id修改文档
              • 主程序测试:
            • id 查看文档数据
              • 主程序测试:
            • 更新文档值
              • 主程序测试:
          • 常用查询案例:
            • 前言:
              • 准备环境
            • 查询所有文档
              • 主程序测试:
            • 分页查询
              • 精准Term 查询 Query
                • 根据id精确匹配
                  • 分词match查询 Query + minimum_should_match占比查:
                    • 多Fieid分词查:
                      • boolean查询,多条件查询:
                        • 过虑器 filter + 范围查 range
                          • 排序
                            • 高亮显示
                              • 测试:
                            • 分组:
                              • 常用场景:
                          相关产品与服务
                          Elasticsearch Service
                          腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档