手机摄影网站/什么是搜索引擎优化
有两个问题:一是es的自动分页的问题,查询得到显示的数据只有十条,但统计命中记录数385条
二是怎么嵌套聚合查询,在下面的查询过程中两个聚合是并列的
1.引入和es同版本的依赖
<!--elasticsearch rest client--><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.4.2</version></dependency>
<properties><java.version>1.8</java.version><!--===注意这里要配置es的版本即使在下面的<dependency>中引入了7.4.2版本的esclient打开侧边的maven可以看到当前模块的es版本是6.4.3这是因为当前模块使用的spring-boot-starter-parent的版本中配置了es的版本为6.4.3如果要覆盖spring-boot-starter-parent的配置 就在这里重新写版本=================--><elasticsearch.version>7.4.2</elasticsearch.version></properties>
2.创建配置类
package com.kaki.gulimall.search.config;import org.apache.http.HttpHost;
import org.elasticsearch.client.HttpAsyncResponseConsumerFactory;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ElasticSearchConfig {/*** 使用 java api 操作 elasticsearch* 1. 导入同版本的依赖 elasticsearch-rest-high-level-client* 2. 编写配置类 @Bean 注入到容器 获取 client 对象* 3. 测试*///这里没有使用 @Bean注解 放到容器中 静态方法 直接通过类名调用 单例模式// 访问es 有安全鉴别 这个方法给请求设置 RequestOptions 官方文档中有public static final RequestOptions COMMON_OPTIONS;static {RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// builder.addHeader("Authorization", "Bearer " + TOKEN);
// builder.setHttpAsyncResponseConsumerFactory(
// new HttpAsyncResponseConsumerFactory
// .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));COMMON_OPTIONS = builder.build();}@Beanpublic RestHighLevelClient getEsClient(){RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.56.10", 9200, "http")));return client;}
}
3、测试类
package com.kaki.gulimall.search;import com.alibaba.fastjson.JSON;
import com.kaki.gulimall.search.config.ElasticSearchConfig;
import com.mysql.cj.QueryBindings;
import lombok.Data;
import lombok.ToString;
import netscape.javascript.JSObject;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Primary;
import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;@RunWith(SpringRunner.class)
@SpringBootTest
public class GulimallSearchApplicationTests {@Autowiredprivate RestHighLevelClient client;//这个错误的意思是xxx类型有不止一个bean,但是这个错误不会影响项目运行,相当于一个warning。//导致这个错误的原因通常是注入的类型有其他的实现类,所以IDEA提示注入的时候会冲突。/*** 通过 client api 操作elasticsearch 下面这个是 保存索引*/@Testpublic void testIndex() throws IOException {
// IndexRequest indexRequest = new IndexRequest("posts")
// .id("1")
// .source("user", "kimchy", //注意一对json中间使用逗号隔开 不是冒号
// "postDate", new Date(),
// "message", "trying out Elasticsearch");IndexRequest indexRequest = new IndexRequest("users");indexRequest.id("1");User user = new User();user.setGender("女");user.setName("zhangsan");user.setSchool("四川大学");// 导入 fastjson 的依赖String jsonString = JSON.toJSONString(user);indexRequest.source(jsonString, XContentType.JSON);//调用方法 执行保存索引 这里是同步执行方式 参照官方文档IndexResponse indexResponse = client.index(indexRequest, ElasticSearchConfig.COMMON_OPTIONS);//下面还可以提取保存后响应数据的内容System.out.println("status :"+indexResponse.status());}/*** 通过 client api 操作elasticsearch 下面这个是 复杂查询*/@Testpublic void conplexQuery() throws IOException {//1. 构造查询对象SearchRequest searchRequest = new SearchRequest("bank");//构造 SearchSourceBuilderSearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchQuery("address","Street"));//构造聚合查询条件TermsAggregationBuilder term_age_aggBuilder = AggregationBuilders.terms("term_age").field("age").size(10);//把聚合查询对象 放入 SearchSourceBuildersearchSourceBuilder.aggregation(term_age_aggBuilder);AvgAggregationBuilder avg_balance_aggBuilder =AggregationBuilders.avg("avg_balance").field("balance");searchSourceBuilder.aggregation(avg_balance_aggBuilder);System.out.println("检索条件 :"+searchSourceBuilder);//把 SearchSourceBuilder 放入 查询对象中searchRequest.source(searchSourceBuilder);//2. 执行查询 得到返回对象SearchResponse searchResponse = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);//3. 从返回对象中获取信息System.out.println(searchResponse.toString());//获取命中的对象SearchHits hits = searchResponse.getHits();// Map map = JSON.parseObject(searchResponse.toString(), Map.class);/*** 注意 这里getTotalHit获取命中的记录数是 385 但只显示了 10条数据* es 的自动分页*/System.out.println("被检索到的记录数 :"+hits.getTotalHits());SearchHit[] hits1 = hits.getHits();for(SearchHit hit:hits1){//把检索到的内容 转成java实体类对象String sourceAsString = hit.getSourceAsString();JsonHitBean jsonHitBean = JSON.parseObject(sourceAsString, JsonHitBean.class);System.out.println(jsonHitBean);}// ctrl + h 查看所有继承类//获取查询结果中的聚合值Aggregations aggregations = searchResponse.getAggregations();Terms term_age = aggregations.get("term_age");//List<? extends Terms.Bucket> buckets = term_age.getBuckets();for(Terms.Bucket bucket : term_age.getBuckets()){System.out.println("年龄 :"+bucket.getKeyAsString()+" ==> "+bucket.getDocCount());}Avg avg_balance = aggregations.get("avg_balance");System.out.println("平均薪资 :"+avg_balance.getValue());}@Data@ToString//生成 toString方法static class JsonHitBean {private int account_number;private int balance;private String firstname;private String lastname;private int age;private String gender;private String address;private String employer;private String email;private String city;private String state;}@Data ///内部类class User{private String name;private String gender;private String school;}@Testpublic void contextLoads() {System.out.println(client);}}