RestHighLevelClient操作
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.15.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.15.2</version>
</dependency>
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class RestClientConfig {
@Value("${es.iphosts:localhost:9200}")
private String ipHosts;
@Value("${es.password:null}")
private String password;
@Value("${es.username:null}")
private String username;
@Bean(destroyMethod = "close")
public RestHighLevelClient restHighLevelClient() {
List<HttpHost> hosts = new ArrayList<>();
String[] iphostArray = ipHosts.split(";");
for (int i = 0; i < iphostArray.length; i++) {
if (StringUtils.isEmpty(iphostArray[i])) {
continue;
}
hosts.add(new HttpHost(iphostArray[i].split(":")[0],
Integer.valueOf(iphostArray[i].split(":")[1]),"http"));
}
Header[] headers = new BasicHeader[2];
headers[0] = new BasicHeader("username",username);
headers[1] = new BasicHeader("password",password);
RestClientBuilder builder = RestClient.builder(hosts.stream().toArray(HttpHost[]::new))
.setDefaultHeaders(headers)
.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder builder) {
return builder.setConnectTimeout(5000 * 1000)
/** 套接字超时(默认为30秒)//更改客户端的超时限制默认30秒现在改为100*1000分钟 */
.setSocketTimeout(6000 * 1000); //
}
});
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
import com.alibaba.fastjson.JSONObject;
import com.example.demo.es.entity.Product;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
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.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedDoubleTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.ParsedSum;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@SpringBootTest
public class EsTest {
@Autowired
private RestHighLevelClient client;
// @Autowired
// public EsTest(RestHighLevelClient restHighLevelClient){
// this.client=restHighLevelClient;
// }
/**
* 查看官网的api
* https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.17/java-rest-high-create-index.html
* @throws IOException
*/
/**
* 创建索引,使用ik分词器
* @throws IOException
*/
@Test
public void createIndex() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("products");
request.settings(Settings.builder()
.put("index.number_of_shards", 3)
.put("index.number_of_replicas", 2)
);
request.mapping(
"{\n" +
" \"properties\": {\n" +
" \"id\": {\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"title\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"price\": {\n" +
" \"type\": \"double\"\n" +
" },\n" +
" \"created_at\": {\n" +
" \"type\": \"date\"\n" +
" },\n" +
" \"description\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\":\"ik_max_word\"\n" +
" },\n" +
" \"brand\": {\n" +
" \"type\": \"keyword\"\n" +
" }\n" +
" }\n" +
" }",
XContentType.JSON);
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse.isAcknowledged());
}
/**
* 插入文档
* @throws IOException
*/
@Test
public void insertDoc() throws IOException {
IndexRequest request=new IndexRequest("products");
Product product=new Product();
product.setId(1);
product.setTitle("小米手机");
product.setPrice(1999.9d);
product.setDescription("小米手机正好");
request.id(product.getId().toString());
request.source(JSONObject.toJSONString(product), XContentType.JSON);
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
System.out.println(indexResponse.getResult());
}
/**
* 根据Id文档
* @throws IOException
*/
@Test
public void updateDocById() throws IOException {
UpdateRequest request=new UpdateRequest();
request.index("products").id("1");
Product product=new Product();
product.setDescription("小米发烧为生");
request.doc(JSONObject.toJSONString(product), XContentType.JSON);
UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
System.out.println(updateResponse.getResult());
}
/**
* 根据Id删除文档
* @throws IOException
*/
@Test
public void delDocById() throws IOException {
//3.删除数据
DeleteRequest deleteRequest=new DeleteRequest();
deleteRequest.index("products").id("1");
DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(deleteResponse.getResult());
}
/**
* 根据Id查询文档
* @throws IOException
*/
@Test
public void getDocById() throws IOException {
GetRequest getRequest=new GetRequest();
getRequest.index("products").id("1");
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
System.out.println("查出的数据为:"+ getResponse.getSourceAsString());
}
/**
* 查询所有文档
* @throws IOException
*/
@Test
public void matchAllTest() throws IOException {
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
query(queryBuilder);
}
public void query(QueryBuilder queryBuilder )throws IOException{
SearchRequest searchRequest=new SearchRequest();
searchRequest.indices("products");
searchRequest.source(new SearchSourceBuilder().query(queryBuilder));
System.out.println("查询DSL为:"+searchRequest.source().toString());
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("返回结果为:"+searchRes.toString());
System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
SearchHit[] hits = searchRes.getHits().getHits();
for (SearchHit hit: hits) {
System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
}
client.close();
}
/**
* 根据关键词term查询
* @throws IOException
*/
@Test
public void termTest() throws IOException {
QueryBuilder queryBuilder = QueryBuilders.termQuery("description","小米");
query(queryBuilder);
}
/**
* 范围range查询
* @throws IOException
*/
@Test
public void rangeTest() throws IOException {
RangeQueryBuilder queryBuilder=QueryBuilders.rangeQuery("price");
queryBuilder.gte(100);
queryBuilder.lt(300);
query(queryBuilder);
}
/**
* 前缀prefix查询
* @throws IOException
*/
@Test
public void prefixTest() throws IOException {
QueryBuilder queryBuilder = QueryBuilders.prefixQuery("description","小米");
query(queryBuilder);
}
/**
* 通配符wildcard查询,?匹配一个,*匹配多个
* title 为keyword,不分词
* @throws IOException
*/
@Test
public void wildcardTest() throws IOException {
QueryBuilder queryBuilder = QueryBuilders.wildcardQuery("title","*红*");
query(queryBuilder);
}
/**
* 模糊fuzzy查询
*
* fuzzy 模糊查询,最大模糊错误,必须现在0-2之间
* 1.搜索关键词长度为2,不允许存在模糊
* 2.搜索关键词长度为3-5,允许一次模糊
* 3.搜索关键词长度大于5,允许最大2次模糊
* @throws IOException
*/
@Test
public void fuzzyTest() throws IOException {
FuzzyQueryBuilder queryBuilder = QueryBuilders.fuzzyQuery("title", "红米大机").fuzziness(Fuzziness.TWO);
query(queryBuilder);
}
/**
* ids查询
* @throws IOException
*/
@Test
public void idsTest() throws IOException {
QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1","3");
query(queryBuilder);
}
/**
* multiMatch多字段查询,基于分词器
* @throws IOException
*/
@Test
public void multiMatchTest() throws IOException {
QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("真棒").field("title").field("description");
query(queryBuilder);
}
/**
* 分页查询 form 起始位,size条数
* 排序查询 sort
* 包含和排查字段
* @throws IOException
*/
@Test
public void pageTest() throws IOException {
SearchRequest searchRequest=new SearchRequest();
searchRequest.indices("products");
SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
//默认10条
query.from(0).size(2);
query.sort("price", SortOrder.DESC);
//需要的字段名称
String[] include={};
//不需要的字段名称
String[] exclude={"created_at"};
query.fetchSource(include,exclude);
searchRequest.source(query);
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
SearchHit[] hits = searchRes.getHits().getHits();
for (SearchHit hit: hits) {
System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
}
client.close();
}
/**
* 高亮查询,不能用matchAllQuery查询
* @throws IOException
*/
@Test
public void highlightTest() throws IOException {
SearchRequest searchRequest=new SearchRequest();
searchRequest.indices("products");
SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.termQuery("description","苹果"));
HighlightBuilder highlightBuilder=new HighlightBuilder();
highlightBuilder.preTags("<font color='red'>");
highlightBuilder.postTags("</font>");
/**
* 需要高亮的字段
*/
highlightBuilder.field("title").field("description");
highlightBuilder.requireFieldMatch(false);
query.highlighter(highlightBuilder);
searchRequest.source(query);
System.out.println("查询DSL为:"+searchRequest.source().toString());
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("返回结果为:"+searchRes.toString());
System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
SearchHit[] hits = searchRes.getHits().getHits();
for (SearchHit hit: hits) {
System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if(highlightFields.containsKey("description")){
System.out.println("description高亮的结果:"+highlightFields.get("description").fragments()[0]);
}
if(highlightFields.containsKey("title")){
System.out.println("title高亮的结果:"+highlightFields.get("title").fragments()[0]);
}
}
client.close();
}
/**
* query :精确查询,查询计算文档得分,并根据得分进行返回
* filter query:过滤查询,用在大数量中筛选出本地查询相关数据,不会计算文档得分,经常使用filter query 结果进行缓存
* 注意:一旦使用query和filter query 。ES 优先执行filter,然后再执行query
* postFilter 中可以搭配term,terms,range,ids,exists
* @throws IOException
*/
@Test
public void filterTest() throws IOException {
SearchRequest searchRequest=new SearchRequest();
searchRequest.indices("products");
SearchSourceBuilder builder = new SearchSourceBuilder().query(QueryBuilders.termQuery("description","手机"));
//builder.postFilter(QueryBuilders.rangeQuery("price").gt(100).lt(200));
//builder.postFilter(QueryBuilders.idsQuery().addIds("1","2"));
//如果某个字段存在
builder.postFilter(QueryBuilders.existsQuery("title"));
searchRequest.source(builder);
System.out.println("查询DSL为:"+searchRequest.source().toString());
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("返回结果为:"+searchRes.toString());
System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
SearchHit[] hits = searchRes.getHits().getHits();
for (SearchHit hit: hits) {
System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
}
client.close();
}
/**
* aggs :聚合查询(aggs) -sql中分组
* @throws IOException
*/
@Test
public void composeTest() throws IOException {
SearchRequest searchRequest=new SearchRequest();
searchRequest.indices("products");
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder=QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.termQuery("title","红米手机"));
boolQueryBuilder.should(QueryBuilders.rangeQuery("price").gt(100).lt(200));
builder.query(boolQueryBuilder);
searchRequest.source(builder);
System.out.println("查询DSL为:"+searchRequest.source().toString());
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("返回结果为:"+searchRes.toString());
System.out.println("总条数为:"+searchRes.getHits().getTotalHits().value);
System.out.println("最大分数为:"+searchRes.getHits().getMaxScore());
SearchHit[] hits = searchRes.getHits().getHits();
for (SearchHit hit: hits) {
System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
}
client.close();
}
/**
* aggs :聚合查询(aggs) -sql中分组
* @throws IOException
*/
@Test
public void aggsTest() throws IOException {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("products");
SearchSourceBuilder builder = new SearchSourceBuilder();
AggregationBuilder aggregationBuilder = AggregationBuilders.terms("priceGroup").field("price");
builder.aggregation(aggregationBuilder);
/**
* 如果不需要返回查询的结果,size=0
* builder.size(0);
*/
searchRequest.source(builder);
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchRes.getHits();
for (SearchHit hit : hits) {
System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
}
Aggregations aggregations = searchRes.getAggregations();
/**
因为是根据Price来分组,price是double类型的,所以用ParsedDoubleTerms,适用于k->v这种的
*/
ParsedDoubleTerms parsedDoubleTerms = aggregations.get("priceGroup");
List<? extends Terms.Bucket> buckets = parsedDoubleTerms.getBuckets();
for (Terms.Bucket bucket:buckets){
System.out.println("key:为"+bucket.getKeyAsString()+",count数量为:"+bucket.getDocCount());
}
client.close();
}
/**
* aggs :聚合查询(aggs) -聚合函数max,min,avg,sum
* @throws IOException
*/
@Test
public void aggsOperateTest() throws IOException {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("products");
SearchSourceBuilder builder = new SearchSourceBuilder();
AggregationBuilder aggregationBuilder = AggregationBuilders.sum("priceSum").field("price");
builder.aggregation(aggregationBuilder);
/**
* 如果不需要返回查询的结果,size=0
* builder.size(0);
*/
searchRequest.source(builder);
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchRes.getHits();
for (SearchHit hit : hits) {
System.out.println("id:为"+hit.getId()+",数据为:"+hit.getSourceAsString());
}
Aggregations aggregations = searchRes.getAggregations();
/**
max 使用ParsedMax处理
min 使用ParsedMin处理
avg 使用 ParsedAvg处理
sum 使用ParsedSum处理
*/
ParsedSum parsedSum = aggregations.get("priceSum");
double sumValue = parsedSum.getValue();
System.out.println("求和值为:"+sumValue);
client.close();
}
/**
* collapse :折叠,比如根据菜系折叠,从每个菜系中选前2名好吃的菜
* <p>
* 下面是根据价格折叠,然后再每个子域中按照title折叠
*
* @throws IOException
*/
@Test
public void collapseTest() throws IOException {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("products");
SearchSourceBuilder builder = new SearchSourceBuilder();
QueryBuilder queryBuilder = QueryBuilders.matchQuery("brand", "vivo");
builder.query(queryBuilder);
CollapseBuilder collapseBuilder = new CollapseBuilder("price");
List<InnerHitBuilder> innerHits = new ArrayList<>();
InnerHitBuilder innerHitBuilder = new InnerHitBuilder();
innerHitBuilder.setName("r_date");
innerHitBuilder.addSort(SortBuilders.fieldSort("created_at").order(SortOrder.DESC));
innerHitBuilder.setSize(10);
innerHitBuilder.setInnerCollapse(new CollapseBuilder("title"));
innerHits.add(innerHitBuilder);
collapseBuilder.setInnerHits(innerHits);
builder.collapse(collapseBuilder);
searchRequest.source(builder);
System.out.println("查询DSL为:" + searchRequest.source().toString());
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchRes.getHits();
for (SearchHit hit : hits) {
System.out.println("id:为" + hit.getId() + ",数据为:" + hit.getSourceAsString());
Map<String, SearchHits> innerHitsRes = hit.getInnerHits();
for (Map.Entry<String, SearchHits> map : innerHitsRes.entrySet()) {
String fieldKey = map.getKey();
SearchHits innerSearchHits = map.getValue();
SearchHit[] innerHitRes = innerSearchHits.getHits();
for (SearchHit h : innerHitRes) {
System.out.println("collapse field: " + fieldKey + ",id:为" + h.getId() + ",数据为:" + h.getSourceAsString());
}
}
}
client.close();
}
/**
* aggs :聚合查询(aggs) -top_hits 取分组中的前几位
*
* @throws IOException
*/
@Test
public void aggsTopHitsTest() throws IOException {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("products");
SearchSourceBuilder builder = new SearchSourceBuilder();
AggregationBuilder aggregationBuilder = AggregationBuilders.topHits("price_top").sort(SortBuilders.fieldSort("price").order(SortOrder.DESC)).size(2);
builder.aggregation(aggregationBuilder);
/**
* 如果不需要返回查询的结果,size=0
* builder.size(0);
*/
builder.size(0);
searchRequest.source(builder);
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchRes.getHits();
for (SearchHit hit : hits) {
System.out.println("id:为" + hit.getId() + ",数据为:" + hit.getSourceAsString());
}
Aggregations aggregations = searchRes.getAggregations();
TopHits topHits = aggregations.get("price_top");
SearchHits hitsRes = topHits.getHits();
for (SearchHit hit : hitsRes.getHits()) {
System.out.println("id:为" + hit.getId() + ",数据为:" + hit.getSourceAsString());
}
client.close();
}
/**
* aggs :聚合查询(aggs) -percentile_ranks 百分比排名
*
* 统计手机在不同的价格区间的占比
* @throws IOException
*/
@Test
public void aggsPercentileRanksTest() throws IOException {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("products");
SearchSourceBuilder builder = new SearchSourceBuilder();
double[] rankVal={200d,300d,500d};
PercentileRanksAggregationBuilder aggregationBuilder = AggregationBuilders.percentileRanks("price_ranks",rankVal);
aggregationBuilder.field("price");
builder.aggregation(aggregationBuilder);
/**
* 如果不需要返回查询的结果,size=0
* builder.size(0);
*/
builder.size(0);
searchRequest.source(builder);
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchRes.getHits();
for (SearchHit hit : hits) {
System.out.println("id:为" + hit.getId() + ",数据为:" + hit.getSourceAsString());
}
Aggregations aggregations = searchRes.getAggregations();
PercentileRanks rercentileRanks = aggregations.get("price_ranks");
for (Percentile entry : rercentileRanks) {
double percent = entry.getPercent(); // Percent
double value = entry.getValue(); // Value
System.out.println("value:"+value+"percent:"+percent);
}
client.close();
}
/**
* 自动补全功能,使用拼音分词器搜索
*
* @throws IOException
*/
@Test
public void autoCompleteTest() throws IOException {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("stars");
SearchSourceBuilder builder = new SearchSourceBuilder();
CompletionSuggestionBuilder completionSuggestionBuilder=new CompletionSuggestionBuilder("name").skipDuplicates(true).size(10);
completionSuggestionBuilder.prefix("liu");
SuggestBuilder suggestBuilder=new SuggestBuilder();
suggestBuilder.addSuggestion("star_name_suggest",completionSuggestionBuilder);
builder.suggest(suggestBuilder);
/**
* 如果不需要返回查询的结果,size=0
* builder.size(0);
*/
builder.size(0);
/**
* 不需要Source可以去掉
*/
builder.fetchSource(false);
searchRequest.source(builder);
System.out.println("查询DSL为:" + searchRequest.source().toString());
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
CompletionSuggestion
suggest = searchRes.getSuggest().getSuggestion("star_name_suggest");
ArrayList<String> list=new ArrayList<>();
suggest.forEach(c->c.getOptions().forEach(f->
list.add( f.getText().toString())
));
list.forEach(System.out::println);
client.close();
}
}
自定义打分
根据业务规则来定制排序规则,如果同时使用sort,那么按照sort来排序,脚本无效
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.filter(QueryBuilders.termsQuery("brand", "vivo"));
Map<String, Object> params = new HashMap(8);
Map<String, Double> scoreMap = new HashMap<>(16);
scoreMap.put("vivo手机", 2d);
scoreMap.put("NEX手机", 1.5d);
scoreMap.put("xplay手机", 1d);
scoreMap.put("iQOO手机", 3d);
params.put("scoreMap", scoreMap);
final String scoreScript =
"HashMap scoreMap = (HashMap)params.scoreMap;double score = 0d;" +
"String title = doc['title'].value;" +
"double price = doc['price'].value;" +
"double phoneScore = 0d; " +
"if(scoreMap.get(title)!=null){" +
"phoneScore = (double)scoreMap.get(title);" +
"} " +
"score = phoneScore*price+_score;" +
"return score;";
ScriptScoreFunctionBuilder scriptScoreFunctionBuilder = ScoreFunctionBuilders.scriptFunction(new Script(Script.DEFAULT_SCRIPT_TYPE, Script.DEFAULT_SCRIPT_LANG, scoreScript, params));
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(boolQueryBuilder, scriptScoreFunctionBuilder).
scoreMode(FunctionScoreQuery.ScoreMode.SUM).boostMode(CombineFunction.SUM);
searchSourceBuilder.query(functionScoreQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchRes.getHits();
for (SearchHit hit : hits) {
System.out.println("分数为:"+hit.getScore()+",数据为:" + hit.getSourceAsString());
}
client.close();
自定义打分(在搜索结果中增加权重)
1.更改了脚本分数的计算方式,增加了Math.log10()函数,让结果更加平稳
2.增加了weight()函数,使结果可以二次排序
SearchRequest searchRequest = new SearchRequest("products");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.filter(QueryBuilders.termsQuery("brand", "vivo"));
Map<String, Object> params = new HashMap(8);
Map<String, Double> scoreMap = new HashMap<>(16);
scoreMap.put("vivo手机", 2d);
scoreMap.put("NEX手机", 1.5d);
scoreMap.put("xplay手机", 1d);
scoreMap.put("iQOO手机", 3d);
params.put("scoreMap", scoreMap);
final String scoreScript =
"HashMap scoreMap = (HashMap)params.scoreMap;double score = 0d;" +
"String title = doc['title'].value;" +
"double price = doc['price'].value;" +
"double phoneScore = 0d; " +
"if(scoreMap.get(title)!=null){" +
"phoneScore = (double)scoreMap.get(title);" +
"} " +
"score = Math.log10(1d+phoneScore*price)+_score;" +
"return score;";
List<FunctionScoreQueryBuilder.FilterFunctionBuilder> filterFunctionBuilderList = new ArrayList<>();
filterFunctionBuilderList.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("price","899.99"),
ScoreFunctionBuilders.weightFactorFunction(10)));
ScriptScoreFunctionBuilder scriptScoreFunctionBuilder = ScoreFunctionBuilders.scriptFunction(new Script(Script.DEFAULT_SCRIPT_TYPE, Script.DEFAULT_SCRIPT_LANG, scoreScript, params));
FunctionScoreQueryBuilder.FilterFunctionBuilder filterFunctionBuilder = new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchAllQuery(), scriptScoreFunctionBuilder);
filterFunctionBuilderList.add(filterFunctionBuilder);
FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = filterFunctionBuilderList.toArray(new FunctionScoreQueryBuilder.FilterFunctionBuilder[filterFunctionBuilderList.size()]);
FunctionScoreQueryBuilder functionScoreQueryBuilder = new FunctionScoreQueryBuilder(boolQueryBuilder, filterFunctionBuilders).
scoreMode(FunctionScoreQuery.ScoreMode.SUM).boostMode(CombineFunction.SUM);
searchSourceBuilder.query(functionScoreQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchRes.getHits();
for (SearchHit hit : hits) {
System.out.println("分数为:"+hit.getScore()+",数据为:" + hit.getSourceAsString());
}
DSL如下
{
"function_score" : {
"query" : {
"bool" : {
"filter" : [
{
"terms" : {
"brand" : [
"vivo"
],
"boost" : 1.0
}
}
],
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
"functions" : [
{
"filter" : {
"term" : {
"price" : {
"value" : "899.99",
"boost" : 1.0
}
}
},
"weight" : 10.0
},
{
"filter" : {
"match_all" : {
"boost" : 1.0
}
},
"script_score" : {
"script" : {
"source" : "HashMap scoreMap = (HashMap)params.scoreMap;double score = 0d;String title = doc['title'].value;double price = doc['price'].value;double phoneScore = 0d; if(scoreMap.get(title)!=null){phoneScore = (double)scoreMap.get(title);} score = Math.log10(1d+phoneScore*price)+_score;return score;",
"lang" : "painless",
"params" : {
"scoreMap" : {
"iQOO手机" : 3.0,
"NEX手机" : 1.5,
"vivo手机" : 2.0,
"xplay手机" : 1.0
}
}
}
}
}
],
"score_mode" : "sum",
"boost_mode" : "sum",
"max_boost" : 3.4028235E38,
"boost" : 1.0
}
}
nested 查询
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("blog_new");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
String nestedPath="comments";
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
MatchQueryBuilder nameMatch = QueryBuilders.matchQuery("comments.name", "steve");
MatchQueryBuilder ageMatch = QueryBuilders.matchQuery("comments.age", 66);
BoolQueryBuilder queryBuilder = boolQueryBuilder.must(nameMatch).must(ageMatch);
NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(nestedPath, queryBuilder, ScoreMode.None);
searchSourceBuilder.query(nestedQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchRes = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchRes.getHits();
for (SearchHit hit : hits) {
System.out.println("数据为:" + hit.getSourceAsString());
}
Nested 更新
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
String nestedPath="comments";
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
MatchQueryBuilder nameMatch = QueryBuilders.matchQuery("comments.name", "steve");
BoolQueryBuilder queryBuilder = boolQueryBuilder.must(nameMatch);
NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(nestedPath, queryBuilder, ScoreMode.None);
searchSourceBuilder.query(nestedQueryBuilder);
UpdateByQueryRequest updateByQueryRequest =new UpdateByQueryRequest();
updateByQueryRequest.indices("blog_new");
updateByQueryRequest.setMaxRetries(3);
String script=" for(e in ctx._source.comments){if (e.name == params.name) {e.age = params.age; e.comment= 'very very good article...';}}";
Map<String, Object> params =new HashMap<>();
params.put("name","steve");
params.put("age",48);
updateByQueryRequest.setScript(new Script(ScriptType.INLINE, "painless", script, params));
updateByQueryRequest.setQuery(nestedQueryBuilder);
client.updateByQuery(updateByQueryRequest,RequestOptions.DEFAULT);
通过Http向ES发送请求,测试于ES7.10版本
public static void httpToES() throws Exception {
try {
RestTemplate restTemplate = new RestTemplate();
String endpoint = "http://localhost:9200/synonym_index/_analyze";
// 设置请求头和请求体
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
Map<String, Object> requestMap = new HashMap<>();
requestMap.put("analyzer", "ik_max_word");
requestMap.put("text", "Hello World");
// 创建 HttpEntity 对象
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestMap, headers);
// 发送 POST 请求,并处理 Elasticsearch 返回的响应
ResponseEntity<String> responseEntity = restTemplate.exchange(endpoint, HttpMethod.POST, requestEntity, String.class);
String responseBody = responseEntity.getBody();
System.out.println(responseBody);
} catch (Exception e){
e.printStackTrace();
}
返回结果
有一些写法可以参考
https://www.kgraph.cn/218.html