Elasticsearch-高级用法

12/23/2023 Elasticsearch

# 经纬度

# 定义

在 Elasticsearch 中,可以将经纬度信息作为 Geo Point 类型存储在文档中。

定义文档映射时,需要指定字段为Geo Point类型:

{
  "mappings": {
    "properties": {
      "location": {
        "type": "geo_point"
      }
    }
  }
}
1
2
3
4
5
6
7
8
9

当我们存储数据时,经纬度可以用两种方式表示:

数组方式:第一个元素是经度,第二个元素是纬度

{
  "location": [120.123, 30.456]
}
1
2
3

对象方式:lon字段表示经度,lat字段表示纬度

{
  "location": {
    "lon": 120.123,
    "lat": 30.456
  }
}
1
2
3
4
5
6

或者

{
  "location": {
    "longtitude": 120.123,
    "latitude": 30.456
  }
}
1
2
3
4
5
6

# 查询

纬度的取值范围为 -90 ~ 90。赤道为0度,北半球为北纬(+),南半球为南纬(-)。

经度的取值范围为-180 ~ 180。一般以英国为0度。东半球为东经(+),西半球为西经(-)。

# Geo Bounding Box

作用:查找位于指定边界框内的所有点。需要提供一个矩形区域的左上角和右下角坐标

{
  "query": {
    "geo_bounding_box": {
      "location": {
        "top_left": {
          "lat": 72.51,
          "lon": 13.37
        },
        "bottom_right": {
          "lat": 12.49,
          "lon": 173.39
        }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# Geo Distance

作用:查找距离指定点在一定范围内的所有点。需要提供一个中心点和最大距离(单位可以是米、千米、英里或英尺)。

{
  "query": {
    "geo_distance": {
      "distance": "10km",
      "location": {
        "lat": 52.52,
        "lon": 13.38
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

# Geo Polygon

作用:查找位于多边形内的所有点。需要提供一个由多个点组成的多边形。

{
  "query": {
    "geo_polygon": {
      "location": {
        "points": [
          [121, 31], [121, 32], [122, 32], [122, 31]
        ]
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

# Geo Shape

作用:查找与指定几何形状相交的点。你可以使用多种几何形状,如点、线、多边形等。

{
  "query": {
    "geo_shape": {
      "location": {
        "shape": {
          "type": "polygon",
          "coordinates": [
            [
              [13.37, 52.51],
              [13.37, 52.53],
              [13.39, 52.53],
              [13.39, 52.51],
              [13.37, 52.51]
            ]
          ]
        }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# copy_to

作用:opy_to 是 Elasticsearch 中的一个映射(mapping)选项,它允许你将一个或多个字段的值复制到另一个字段。

映射定义:

{
  "mappings": {
    "properties": {
      "first_name": {
        "type": "text",
        "copy_to": "full_name"
      },
      "last_name": {
        "type": "text",
        "copy_to": "full_name"
      },
      "full_name": {
        "type": "text"
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 自动补全

准备工作

  1. 下载elasticsearch;
  2. 下载elasticsearch对应版本的插件:
    1. ik分词器(中文分词器) (opens new window)
    2. pinyin分词器(处理拼音) (opens new window)
  3. 将插件解压,并放到下载elasticsearch的插件目录下(/elasticsearch-7.15.0/plugins);
       unzip elasticsearch-analysis-ik-7.15.0.zip -d ik  # 解压文件,并将内容防止到 ik 目录下(不存在则创建)
       mv ik elasticsearch-7.15.0/plugins/
    
    1
    2
  4. 重启elasticsearch;

定义索引时,进行自动补全配置

PUT http://192.168.1.6:9200/my_idx
Content-Type: application/json

{
  "settings": {
    "analysis": {
      "analyzer": {
        "king_word": {
          "tokenizer": "ik_max_word",
          "filter": [
            "custom_pinyin_filter"
          ]
        },
        "king_completion": {
          "tokenizer": "keyword",
          "filter": "custom_pinyin_filter"
        }
      },
      "filter": {
        "custom_pinyin_filter": {
          "type": "pinyin",
          "keep_joined_full_pinyin": true,
          "keep_original": true,
          "remove_duplicated_term": true,
          "none_chinese_pinyin_tokenize": false
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "king_word",
        "search_analyzer": "ik_max_word"
      },
      "name": {
        "type": "completion",
        "analyzer": "king_completion"
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

创建倒排索引时:

{
	"id": 1,
	"name": "柿子"
}

{
	"id": 2,
	"name": "狮子"
}


1
2
3
4
5
6
7
8
9
10
11

假设es中使用用自定义分词器分词后这两个索引在数据库中保存的格式为:

词条 文档编号
狮子 1
sz 1,2
shizi 1,2
柿子 2

当用户进行搜索时输入: “我去动物园看狮子” 后发现,柿子也被搜索到了。

原因是es 会对输入内容进行分词,分词中包含狮子,运用拼音过滤器 后生成了(sz,shizi,狮子),导致同时将 狮子和 sz 的倒排索引同时查找出来,结果就是搜索的内容同时包含 柿子。

解决:

在进行索引映射时,我们需要同时指定2个analyzer,格式如下:

{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "king_word",
        "search_analyzer": "ik_smart"
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

创建索引时,我们需要生产(sz,shizi,狮子)对应的词条,但是在搜索时,我们需要按照用户输入的内容进行搜索,而不进行扩展。

定义自动补全字段

{
  "mappings": {
    "properties": {
      "title": {
        "type": "completion"
      }
    }
  }
}
1
2
3
4
5
6
7
8
9

设置补全数据

POST hotel/_doc

{
  "title": ["r", "rj"]
}
1
2
3
4
5

自动补全查询

GET /hotel/_search

{
  "suggest": {
    "title_suggest": {
      "text": "s"   //关键字,搜索前缀
      "completion": {
      	"field": "title",
       	"skip_duplicates": true,  // 跳过重复
      	"size": 10
    	}
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

引入pinyin分词器插件

拼音分词器: