DSL查询文档
- 查询所有:查询出所有数据,一般测试用。例如:match_all
全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:
- match_query
- multi_match_query
精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:
- ids
- range
- term
地理(geo)查询:根据经纬度查询。例如:
- geo_distance
- geo_bounding_box
复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:
- bool
- function_score
1.全文检索查询
#match查询 //搜索字段越多,对查询性能影响越大,因此建议采用copy_to,然后单字段查询的方式比较好
GET /hotel/_search
{
"query": {
"match": {
"all":"上海外滩"
}
}
}
#multi_match查询
GET /hotel/_search
{
"query": {
"multi_match": {
"query": "如家",
"fields": ["name","business"]
}
}
}
2.精准查询
2.1term查询
因为精确查询的字段搜是不分词的字段,因此查询的条件也必须是不分词的词条。查询时,用户输入的内容跟自动值完全匹配时才认为符合条件。如果用户输入的内容过多,反而搜索不到数据。
//term 精准查询
GET /hotel/_search
{
"query": {
"term": {
"name": {
"value": "上海"
}
}
}
}
2.22.range查询
范围查询,一般应用在对数值类型做范围过滤的时候。比如做价格范围过滤
//range 范围查询
GET /hotel/_search
{
"query": {
"range": {
"price": {
"gte": 100,
"lte": 200
}
}
}
}
3.地理坐标查询
所谓的地理坐标查询,其实就是根据经纬度查询
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-queries.html
常见的使用场景包括:
- 携程:搜索我附近的酒店
- 滴滴:搜索我附近的出租车
- 微信:搜索我附近的人
#geo_bounding_box矩形查询
GET /hotel/_search
{
"query": {
"geo_bounding_box":{
"location":{
"top_left":{
"lat":31.1,
"lon":121.5
},
"bottom_right":{
"lat":30.9,
"lon":121.7
}
}
}
}
}
#geo_distance 距离查询
GET /hotel/_search
{
"query": {
"geo_distance":{
"distance":"100km",
"location":"39.909187,116.397455" //天安门
}
}
}
4.算分函数查询
function score 查询中包含四部分内容:
- 原始查询条件:query部分,基于这个条件搜索文档,并且基于BM25算法给文档打分,原始算分(query score)
- 过滤条件:filter部分,符合该条件的文档才会重新算分
算分函数:符合filter条件的文档要根据这个函数做运算,得到的函数算分(function score),有四种函数
- weight:函数结果是常量
- field_value_factor:以文档中的某个字段值作为函数结果
- random_score:以随机数作为函数结果
- script_score:自定义算分函数算法
运算模式:算分函数的结果、原始查询的相关性算分,两者之间的运算方式,包括:
- multiply:相乘
- replace:用function score替换query score
- 其它,例如:sum、avg、max、min
#算分查询
GET /hotel/_search
{
"query": {
"function_score": {
"query": {
"match": {
"all": "外滩"
}
},
"functions": [
{
"filter": {
"term": {
"brand": "如家"
}
},
"weight": 10 //加权重
}
],
"boost_mode": "sum"
}
}
}
5.布尔查询
布尔查询是一个或多个查询子句的组合,每一个子句就是一个子查询。子查询的组合方式有:
- must:必须匹配每个子查询,类似“与”
- should:选择性匹配子查询,类似“或”
- must_not:必须不匹配,不参与算分,类似“非”
- filter:必须匹配,不参与算分
示例
需求:搜索名字包含“如家”,价格不高于400,在坐标39.909187,116.397455周围10km范围内的酒店。
分析:
- 名称搜索,属于全文检索查询,应该参与算分。放到must中
- 价格不高于400,用range查询,属于过滤条件,不参与算分。放到must_not中
- 周围10km范围内,用geo_distance查询,属于过滤条件,不参与算分。放到filter中
#布尔查询
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "如家",
"fields": [
"name"
]
}
}
],
"must_not": [
{
"range": {
"price": {
"gte": 0,
"lte": 400
}
}
}
],
"filter": [
{
"geo_distance": {
"distance": "10km",
"location": "39.909187,116.397455"
}
}
]
}
}
}
搜索结果操作
搜索结果
排序sort
GET /hotel/_search
{
"query": {
"match_all": {
}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
地理坐标排序
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"_geo_distance": {
"order": "desc",
"location": {
"lat": 31.208553,
"lon": 121.518552
},
"unit": "km"
}
}
]
}
分页排序
GET /hotel/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5,
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
高亮
如果要对非搜索字段高亮,则需要添加一个属性:required_field_match=false
GET /hotel/_search
{
"query": {
"match": {
"all": "如家"
}
},
"highlight": {
"fields": {
"name": {
"require_field_match": "false"
}
}
}
}
// 查询条件,高亮一定要使用全文检索查询
GET /hotel/_search
{
"query": {
"match": {
"brand": "如家"
}
},
"highlight": {
"fields": {
"brand": {
"pre_tags": "<em>",
"post_tags": "</em>"
}
}
}
}
感谢分享