Elasticsearch系列---几个高级功能 (3)

例如:

PUT /music { "mappings": { "children": { "properties": { "name": { "type": "text", "analyzer": "ik_max_word" }, "content": { "type": "text", "analyzer": "ik_max_word", "term_vector" : "with_positions_offsets" } } } } }

一般情况下,用plain highlight也就足够了,不需要做其他额外的设置
如果对高亮的性能要求很高,可以尝试启用unified highlight
如果field的值特别大,超过了1M,那么可以用fast vector highlight

自定义高亮html标签

我们知道高亮的默认标签是<em>,这个标签可以自己定义的,然后使用自己喜欢的样式:

GET /music/children/_search { "query": { "match": { "content": "Love" } }, "highlight": { "pre_tags": ["<tag1>"], "post_tags": ["</tag2>"], "fields": { "content": { "type": "plain" } } } } 高亮片段fragment的设置

针对一些很长的文本,我们不可能在页面上完整显示的,我们需要只显示有关键词的上下文即可,这里设置fragment就行:

GET /_search { "query" : { "match": { "content": "friend" } }, "highlight" : { "fields" : { "content" : {"fragment_size" : 150, "number_of_fragments" : 3, "no_match_size": 150 } } } }

fragment_size: 设置要显示出来的fragment文本判断的长度,默认是100。

number_of_fragments:你可能你的高亮的fragment文本片段有多个片段,你可以指定就显示几个片段。

地理位置

现在基于地理位置的app层出不穷,支持地理位置的组件也有不少,Elasticsearch也不例外,并且ES可以把地理位置、全文搜索、结构化搜索和分析结合到一起,我们来看一下。

geo point数据类型

Elasticsearch基于地理位置的搜索,有一个专门的对象geo_point存储地理位置信息(经度,纬度),并且提供了一些基本的查询方法,如geo_bounding_box。

建立geo_point类型的mapping

PUT /location { "mappings": { "hotels": { "properties": { "location": { "type": "geo_point" }, "content": { "type": "text" } } } } } 插入数据

推荐使用如下插入数据方式:

#latitude:维度,longitude:经度 PUT /location/hotels/1 { "content":"7days hotel", "location": { "lon": 113.928619, "lat": 22.528091 } }

还有两种插入数据的方式,但特别容易搞混经纬度的位置,所以不是很推荐:

# location中括号内,前一个是经度,后一个是纬度 PUT /location/hotels/2 { "content":"7days hotel ", "location": [113.923567,22.523988] } # location中,前一个是纬度,后一个是经度 PUT /location/hotels/3 { "text": "7days hotel Orient Sunseed Hotel", "location": "22.521184, 113.914578" } 查询方法

geo_bounding_box查询,查询某个矩形的地理位置范围内的坐标点

GET /location/hotels/_search { "query": { "geo_bounding_box": { "location": { "top_left":{ "lon": 112, "lat": 23 }, "bottom_right":{ "lon": 114, "lat": 21 } } } } } 常见查询场景 geo_bounding_box方式 GET /location/hotels/_search { "query": { "bool": { "must": [ {"match_all": {}} ], "filter": { "geo_bounding_box": { "location": { "top_left":{ "lon": 112, "lat": 23 }, "bottom_right":{ "lon": 114, "lat": 21 } } } } } } } geo_polygon方式,三个点组成的多边形(三角形)区域

支持多边形,只是这个过滤器使用代价很大,尽量少用。

GET /location/hotels/_search { "query": { "bool": { "must": [ {"match_all": {}} ], "filter": { "geo_polygon": { "location": { "points": [ {"lon": 115,"lat": 23}, {"lon": 113,"lat": 25}, {"lon": 112,"lat": 21} ] } } } } } } geo_distance方式

根据当前位置的距离进行搜索,非常实用

GET /location/hotels/_search { "query": { "bool": { "must": [ {"match_all": {}} ], "filter": { "geo_distance": { "distance": 500, "location": { "lon": 113.911231, "lat": 22.523375 } } } } } } 按距离排序

根据当前位置进行条件搜索,会指定一个距离的上限,2km或5km,并且符合条件查询的结果显示与当前位置的距离(可以指定单位),并且按从近到远排序,这个是非常常用的场景。

请求示例:

GET /location/hotels/_search { "query": { "bool": { "must": [ {"match_all": {}} ], "filter": { "geo_distance": { "distance": 2000, "location": { "lon": 113.911231, "lat": 22.523375 } } } } }, "sort": [ { "_geo_distance": { "location": { "lon": 113.911231, "lat": 22.523375 }, "order": "asc", "unit": "m", "distance_type": "plane" } } ] }

filter.geo_distance.distance: 最大的距离,这里是2000m

_geo_distance: 固定写法,下面为指定位置的经纬度

order: 排序方式,asc或desc

unit: 距离的单位,m/km都行

distance_type: 计算距离的方式,sloppy_arc (默认值), arc (精准的) and plane (最快速的)

响应如下:

"hits": [ { "_index": "location", "_type": "hotels", "_id": "3", "_score": null, "_source": { "text": "7days hotel Orient Sunseed Hotel", "location": "22.521184, 113.914578" }, "sort": [ 421.35435857277366 ] }, { "_index": "location", "_type": "hotels", "_id": "2", "_score": null, "_source": { "content": "7days hotel", "location": [ 113.923567, 22.523988 ] }, "sort": [ 1268.8952707727062 ] }

sort里面的内容,就是与当前位置的地面距离,单位是m。

统计我当前位置几个范围内酒店的数量

unit表示距离单位,常用的是mi和km。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsppjf.html