public class HotelSearchTest {
private RestHighLevelClient client;
@Test
void testMatchAll() throws IOException {
//准备request
SearchRequest request = new SearchRequest("hotel");
//准备dsl
request.source().query(QueryBuilders.matchAllQuery());
//发送请求
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = search.getHits();
//获取总条数
long value = hits.getTotalHits().value;
System.out.println(value);
//获取数据
SearchHit[] hits1 = hits.getHits();
for (SearchHit documentFields : hits1) {
String sourceAsString = documentFields.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
System.out.println(hotelDoc);
}
}
@Test
void testMatch() throws IOException {
//准备request
SearchRequest request = new SearchRequest("hotel");
//准备dsl
request.source().query(QueryBuilders.matchQuery("all", "如家"));
//发送请求
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
//响应解析
handleResponse(search);
}
@Test
void testTerm() throws IOException {
//准备request
SearchRequest request = new SearchRequest("hotel");
//准备dsl
request.source().query(QueryBuilders.termQuery("city", "杭州"));
//发送请求
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
//响应解析
handleResponse(search);
}
@Test
void testRange() throws IOException {
//准备request
SearchRequest request = new SearchRequest("hotel");
//准备dsl
request.source().query(QueryBuilders.rangeQuery("price").gte(100).lte(500));
//发送请求
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
//响应解析
handleResponse(search);
}
@Test
void testBool() throws IOException {
//准备request
SearchRequest request = new SearchRequest("hotel");
//准备boolquery
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.termQuery("city", "上海"));
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(500));
//准备dsl
request.source().query(boolQueryBuilder);
//发送请求
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
//响应解析
handleResponse(search);
}
@Test
void testPageAndSort() throws IOException {
//页码,每页大小
int page = 1, size = 5;
//准备request
SearchRequest request = new SearchRequest("hotel");
//准备dsl
request.source().query(QueryBuilders.matchAllQuery());
//排序 sort
request.source().sort("price", SortOrder.ASC);
//分页from
request.source().from((page - 1) * size).size(5);
//发送请求
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
//响应解析
handleResponse(search);
}
@Test
void testHighlight() throws IOException {
//页码,每页大小
int page = 1, size = 5;
//准备request
SearchRequest request = new SearchRequest("hotel");
//准备dsl
//定义查询字段
request.source().query(QueryBuilders.matchQuery("all", "如家"));
request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
//发送请求
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
//响应解析
handleResponse(search);
}
private void handleResponse(SearchResponse search) {
SearchHits hits = search.getHits();
//获取总条数
long value = hits.getTotalHits().value;
System.out.println(value);
//获取数据
SearchHit[] hits1 = hits.getHits();
for (SearchHit hit : hits1) {
String sourceAsString = hit.getSourceAsString();
//反序列化
HotelDoc hotelDoc = JSON.parseObject(sourceAsString, HotelDoc.class);
//获取高亮结果
Map
if (!CollectionUtils.isEmpty(highlightFields)) {
//根据名字获取高亮结果
HighlightField name = highlightFields.get("name");
//获取高亮值
String s = name.getFragments()[0].toString();
hotelDoc.setName(s);
}
System.out.println(hotelDoc);
}
}
@Test
void testAggregation() throws IOException {
//准备 request
SearchRequest request = new SearchRequest("hotel");
request.source().size(0);
request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(20));
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
Aggregations aggregations = search.getAggregations();
Terms brandAgg = aggregations.get("brandAgg");
List extends Terms.Bucket> buckets = brandAgg.getBuckets();
for (Terms.Bucket bucket : buckets) {
String s = bucket.getKeyAsString();
System.out.println(s);
}
}
@Test
void testSuggest() throws IOException {
SearchRequest request = new SearchRequest("hotel");
request.source().suggest(new SuggestBuilder()
.addSuggestion("suggestions"
,SuggestBuilders.completionSuggestion("suggestion")
.prefix("h")
.size(20)
.skipDuplicates(true)));
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
Suggest suggest = response.getSuggest();
//根据不全查询名称获取不全结果
CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
List
for (CompletionSuggestion.Entry.Option option : options) {
String s = option.getText().toString();
System.out.println(s);
}
}
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.78.129:9200")));
}
@AfterEach
void tearDown() throws IOException {
client.close();
}
}
service类
@Service
public class HotelService extends ServiceImpl
@Autowired
private RestHighLevelClient client;
@Override
public PageResult search(RequestParams params) {
try {
SearchRequest request = new SearchRequest("hotel");
//构建query
buildBasicQuery(params, request);
//分页搜索
int page = params.getPage();
int size = params.getSize();
request.source().from((page - 1) * size).size(size);
//排序功能实现
String location = params.getLocation();
if (location != null && location.equals("")) {
request.source()
.sort(SortBuilders.geoDistanceSort("location",
new GeoPoint(location)).order(SortOrder.ASC)
.unit(DistanceUnit.KILOMETERS));
}
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//解析响应
return handleResponse(response);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public Map
try {
SearchRequest request = new SearchRequest("hotel");
//添加query信息
buildBasicQuery(params, request);
request.source().size(0);
buildAggregation(request);
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
Map
Aggregations aggregations = search.getAggregations();
List
map.put("品牌", brandAgg);
List
map.put("城市", cityAgg);
List
map.put("品牌", starAgg);
return map;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public List
try {
SearchRequest request = new SearchRequest("hotel");
request.source().suggest(new SuggestBuilder().addSuggestion("suggestions", SuggestBuilders.completionSuggestion("suggestion")
.size(20)
.skipDuplicates(true)
.prefix(prefix)));
List
// request.source().suggest(new SuggestBuilder().addSuggestion("games", SuggestBuilders.completionSuggestion("suggestions").size(2).prefix("sd").skipDuplicates(true)))
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
Suggest suggest = search.getSuggest();
CompletionSuggestion suggestions = suggest.getSuggestion("suggestions");
List
for (CompletionSuggestion.Entry.Option option : options) {
String s = option.getText().toString();
list.add(s);
}
return list;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void deleteById(Long id) {
try {
DeleteRequest request = new DeleteRequest("hotel", id.toString());
client.delete(request, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void insertById(Long id) {
try {
Hotel byId = getById(id);
HotelDoc hotelDoc = new HotelDoc(byId);
IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
request.source(JSON.toJSonString(hotelDoc), XContentType.JSON);
client.index(request, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private List
List
Terms brandAgg = aggregations.get(agg);
List extends Terms.Bucket> buckets = brandAgg.getBuckets();
for (Terms.Bucket bucket : buckets) {
String keyAsString = bucket.getKeyAsString();
list.add(keyAsString);
}
return list;
}
private void buildAggregation(SearchRequest request) {
request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(100));
request.source().aggregation(AggregationBuilders.terms("cityAgg").field("city").size(100));
request.source().aggregation(AggregationBuilders.terms("starAgg").field("starName").size(100));
}
private void buildBasicQuery(RequestParams params, SearchRequest request) {
//关键字搜索 query
//构建booleanQuery
String key = params.getKey();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//关键字搜索
if (key == null || "".equals(key)) {
boolQueryBuilder.must(QueryBuilders.matchAllQuery());
} else {
boolQueryBuilder.must(QueryBuilders.matchQuery("all", key));
}
// 条件过滤
//城市判断
if (params.getCity() != null && !params.getCity().equals("")) {
boolQueryBuilder.filter(QueryBuilders.termQuery("city", params.getCity()));
}
//品牌条件
if (params.getBrand() != null && !params.getBrand().equals("")) {
boolQueryBuilder.filter(QueryBuilders.termQuery("brand", params.getBrand()));
}
//星级判断
if (params.getStarName() != null && !params.getStarName().equals("")) {
boolQueryBuilder.filter(QueryBuilders.termQuery("brand", params.getStarName()));
}
//价格判断
if (params.getMinPrice() != null && params.getMaxPrice() != null) {
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(params.getMaxPrice()).lte(params.getMinPrice()));
}
//2.算分控制
FunctionScoreQueryBuilder functionScoreQueryBuilder =
QueryBuilders.functionScoreQuery(
//原始查询,相关性算分的查询
boolQueryBuilder,
//function score的数组
new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
//其中一个functionscore元素
new FunctionScoreQueryBuilder.FilterFunctionBuilder(
//过滤条件
QueryBuilders.termQuery("idAD", true),
//算分函数
ScoreFunctionBuilders.weightFactorFunction(5)
)
});
request.source().query(functionScoreQueryBuilder);
}
private PageResult handleResponse(SearchResponse response) {
SearchHits searchHits = response.getHits();
//获取总条数
long total = searchHits.getTotalHits().value;
System.out.println(total);
List
//获取数据
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
String json = hit.getSourceAsString();
//反序列化
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
//获取排序值的公里数
Object[] sortValues = hit.getSortValues();
if (sortValues.length > 0) {
Object sortValue = sortValues[0];
hotelDoc.setDistance(sortValue);
}
hotels.add(hotelDoc);
}
return new PageResult(total, hotels);
}
}
es笔记liux下
首先安装部es,配置堆内存 ,单点模式,数据卷,还有映射端口,创建网络
docker network create (自定义名称)
从dockerhub上面拉取es,并配置运行
docker pull elasticsearch:(自定义版本)
docker run -d
--name es
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m"
-e "discovery.type=single-node"
-v es-data:/usr/share/elasticsearch/data
-v es-plugins:/usr/share/elasticsearch/plugins
--privileged
--network es-net
-p 9200:9200
-p 9300:9300
elasticsearch://根据需求进行填写(版本号)
安装kibana
docker run -d --name kibana -e ELASTICSEARCH_HOSTS=http://es:9200 --network=es-net 和es在同一个网络 -p 5601:5601 kibana://根据需求进行填写(版本号)
官网下载分词器,放到esconfig目录下
如果要自行扩展词典
在IKAnalyzer.cfg.xml配置文件内容添加:
IK Analyzer 扩展配置 ext.dic
新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改
里面可以填写所想要的各种词语,
详情百度
可以配置停用敏感词,毒品等
在目录下stopword.dic内添加词语即可,在配置文件中进行配置
自定义分词器// 自定义拼音分词器
PUT /test
{
"settings": {
"analysis": {
"analyzer": {
"my_analyzer": {
"tokenizer": "ik_max_word",
"filter": "py"
}
},
"filter": {
"py": {
"type": "pinyin",
"keep_full_pinyin": false,
"keep_joined_full_pinyin": true,
"keep_original": true,
"limit_first_letter_length": 16,
"remove_duplicated_term": true,
"none_chinese_pinyin_tokenize": false
}
}
}
}
}
POST /test/_doc/1
{
"id": 1,
"name": "狮子"
}
POST /test/_doc/2
{
"id": 2,
"name": "虱子"
}
GET /test/_search
{
"query": {
"match": {
"name": "掉入狮子笼咋办"
}
}
}
// 自动补全的索引库
PUT test
{
"mappings": {
"properties": {
"title":{
"type": "completion"
}
}
}
}
// 示例数据
POST test/_doc
{
"title": ["Sony", "WH-1000XM3"]
}
POST test/_doc
{
"title": ["SK-II", "PITERA"]
}
POST test/_doc
{
"title": ["Nintendo", "switch"]
}
// 自动补全查询
POST /test/_search
{
"suggest": {
"title_suggest": {
"text": "s", // 关键字
"completion": {
"field": "title", // 补全字段
"skip_duplicates": true, // 跳过重复的
"size": 10 // 获取前10条结果
}
}
}
}
索引库创建
// 自定义数据索引库
PUT /hotel
{
"settings": {
"analysis": {
"analyzer": {
"text_anlyzer": {
"tokenizer": "ik_max_word",
"filter": "py"
},
"completion_analyzer": {
"tokenizer": "keyword",
"filter": "py"
}
},
"filter": {
"py": {
"type": "pinyin",
"keep_full_pinyin": false,
"keep_joined_full_pinyin": true,
"keep_original": true,
"limit_first_letter_length": 16,
"remove_duplicated_term": true,
"none_chinese_pinyin_tokenize": false
}
}
}
},
"mappings": {
"properties": {
"id":{
"type": "keyword"
},
"name":{
"type": "text",
"analyzer": "text_anlyzer",
"search_analyzer": "ik_smart",
"copy_to": "all"
},
"address":{
"type": "keyword",
"index": false
},
"price":{
"type": "integer"
},
"score":{
"type": "integer"
},
"brand":{
"type": "keyword",
"copy_to": "all"
},
"city":{
"type": "keyword"
},
"starName":{
"type": "keyword"
},
"business":{
"type": "keyword",
"copy_to": "all"
},
"location":{
"type": "geo_point"
},
"pic":{
"type": "keyword",
"index": false
},
"all":{
"type": "text",
"analyzer": "text_anlyzer",
"search_analyzer": "ik_smart"
},
"suggestion":{
"type": "completion",
"analyzer": "completion_analyzer"
}
}
}
}
索引库查询语法
1.自动补全查询
GET /(索引库名称)/_search
{
"suggest": {
"suggestions": { //自定义
"text": "sd",//
"completion": {
"field": "suggestion", //和创建的相对应
"skip_duplicates":true, //是否筛选重复
"size":10
}
}
}
}
2.查询全部
GET /hotel/_search
{
"query": {
"match_all": {}
}
}
3.嵌套聚合
#嵌套聚合
GET /(索引库名称)/_search
{
"size": 0,
"aggs": {
"prantAgg": {//自定义名称
"terms": {
"field": "字段名",
"size": 10,
"order": {
"scoreAgg.avg": "desc"//排列顺序
}
},
"aggs": {
"scoreAgg": {//自定义名称
"stats": {
"field": "字段名"
}
}
}
}
}
}
4.根据距离查询
GET /(索引库名称)/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"_geo_distance": {
"location": {//距离字段
"lat": 31.034661,
"lon": 121.612282
},
"order": "asc",//排序顺序
"unit": "km" //单位
}
}
]
}
帅选十公里以内的
GET /(索引库名称)/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "如家" //名字必须含有如家的
}
}
],
"must_not": [
{"range": { //价格不得超过500
"price": {
"gte": 500
}
}}
],
"filter": [
{"geo_distance": { //指定距离
"distance": "10km",//定义距离
"location": {
"lat": 31.21,
"lon": 121.5
}
}}
]
}
}
}
功能查询
GET /(索引库名称)/_search
{
"query": {
"function_score": {
"query": {
"match": {
"all": "外滩"
}
},
"functions": [
{
"filter": {
"term": {
"brand": "如家"
}
}
, "weight": 10
}
],
"boost_mode": "sum" //相加的方式,filter内不参与算分制度
}
}
}



