首次使用Elasticsearch
大家好,由于今年即将结束,我打算在剩下的时间里开始学习Elasticsearch!这也包含了我想在我的主要工作中引入它的决心!
实现目标
只要我做,就会有一个目标来驱动我!
-
- テキスト検索
-
- 緯度経度検索
- 時間検索
我們的目標是在本地測試環境中達到能夠的目標!
首先要营造一个良好的环境。
下载Elasticsearch(版本:7.5.0)
https://www.elastic.co/jp/downloads/elasticsearch
解压文件,启动Elasticsearch!
$ bin/elasticsearch
publish_address {127.0.0.1:9200}, bound_addresses {[::1]:9200}, {127.0.0.1:9200}
看起来在9200端口上启动了!
请下载Kibana(版本:7.5.0)
https://www.elastic.co/jp/downloads/kibana
Kibana 已启动!
*为了从浏览器连接到 ElasticSearch,需要 Kibana。
$ bin/kibana
http server running at http://localhost:5601
Kibana已成功在5601端口上启动!
试试从Kibana中注册和获取数据。
使用浏览器确认刚刚启动的Kibana在 http://localhost:5601 上,并打开开发工具控制台。
您可以从控制台向刚刚启动的Elasticsearch(http://localhost:9200)发起请求。
首先,需要进行数据注册。
这次将注册两个虚拟店铺的数据。
POST /restaurants/_doc
{
"name": "太平洋に浮かぶレストラン"
}
POST /restaurants/_doc
{
"name": "日本海に浮かぶレストラン"
}
然后,获取已注册的数据。
我将尝试不限制搜索条件进行搜索。
GET /restaurants/_search
可以获取两个无事务的数据!
"hits" : [
{
"_index" : "restaurants",
"_type" : "_doc",
"_id" : "5idkDG8Br1D6GrZbRdpB",
"_score" : 1.0,
"_source" : {
"name" : "太平洋に浮かぶレストラン"
}
},
{
"_index" : "restaurants",
"_type" : "_doc",
"_id" : "5ydkDG8Br1D6GrZbSdoz",
"_score" : 1.0,
"_source" : {
"name" : "日本海に浮かぶレストラン"
}
}
]
既然准备工作完成了,现在开始实现我们设定的目标吧!
搜索文字
使用文本搜索可以通过在查询中使用匹配来筛选。如果要获取包含“海”字的店铺,可以尝试在名称中指定“海”并发起请求。
GET /restaurants/_search
{
"query": {
"match": {
"name": "海"
}
}
}
刚刚注册的“悬浮在日本海上的餐厅”已经成功获取!
"hits" : [
{
"_index" : "restaurants",
"_type" : "_doc",
"_id" : "5ydkDG8Br1D6GrZbSdoz",
"_score" : 0.6931472,
"_source" : {
"name" : "日本海に浮かぶレストラン"
}
}
]
此外,据称SQL也可以作为参数传递,如果尝试按照下面的方式发出请求
POST /_sql?format=json
{
"query": "SELECT * FROM restaurants where name like '%海%'"
}
目前可以获取到的是位于日本海上的餐厅,与之前的返回值不同。
{
"columns" : [
{
"name" : "name",
"type" : "text"
}
],
"rows" : [
[
"日本海に浮かぶレストラン"
]
]
}
似乎还可以进行逻辑表达式和否定的高亮搜索,以确定匹配的单词,但我们现在将加快进入目标2的步伐。
經緯度搜尋的目標2.
首先,按照之前的方式,添加一个带有纬度经度信息的位置,然后注册数据。
POST /restaurants/_doc
{
"name": "太平洋に浮かぶレストラン",
"location": {
"lat": "29.651658",
"lon": "156.085510"
}
}
POST /restaurants/_doc
{
"name": "日本海に浮かぶレストラン",
"location": {
"lat": "38.956739",
"lon": "134.230957"
}
}
为了使经纬度搜索可行,必须将注册的经纬度数据映射到geo point类型。
当我们尝试在/restaurants/_mapping上查看当前数据的映射信息时
GET /restaurants/_mapping
把原本儲存為緯度經度資訊的位置,不小心拿來當作文字資訊存入了,這樣無法進行緯度經度搜尋。
"location" : {
"properties" : {
"lat" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"lon" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
重新调整心态,重新进行注册!
首先,将注册数据暂时删除。
DELETE restaurants
然后,定义映射(将纬度经度输入位置的geo_type和映射)。
PUT /restaurants
PUT /restaurants/_mapping
{
"properties": {
"location": {
"type": "geo_point"
}
}
}
然后,重新注册
POST /restaurants/_doc
{
"name": "太平洋に浮かぶレストラン",
"location": {
"lat": "29.651658",
"lon": "156.085510"
}
}
POST /restaurants/_doc
{
"name": "日本海に浮かぶレストラン",
"location": {
"lat": "38.956739",
"lon": "134.230957",
}
}
当我再次确认映射信息时
GET /restaurants/_mapping
可以确认type为geo_point!
"location" : {
"type" : "geo_point"
}
现在已经准备好了,可以进行经纬度搜索!
试着将当前位置设为日本海并进行搜索(按照距离从近到远排序)。
GET /restaurants/_search
{
"sort": [
{
"_geo_distance": {
"location": {
"lat": 38.956739,
"lon": 134.230957
},
"order": "asc"
}
}
]
}
成功得到了日本海的餐厅,正如计划所愿!目标2已完成!
"hits" : [
{
"_index" : "restaurants",
"_type" : "_doc",
"_id" : "7SdvDG8Br1D6GrZbYdoH",
"_score" : null,
"_source" : {
"name" : "日本海に浮かぶレストラン",
"location" : {
"lat" : "38.956739",
"lon" : "134.230957"
}
},
"sort" : [
0.0
]
},
{
"_index" : "restaurants",
"_type" : "_doc",
"_id" : "7CdvDG8Br1D6GrZbWNqp",
"_score" : null,
"_source" : {
"name" : "太平洋に浮かぶレストラン",
"location" : {
"lat" : "29.651658",
"lon" : "156.085510"
}
},
"sort" : [
2250187.1065158164
]
}
]
寻找时间的目标3
时间搜索可以按照经度纬度搜索的方式进行!
首先,我们需要定义营业时间的映射信息,包括营业开始时间 business_start_time 和结束时间 business_end_time!
PUT /restaurants/_mapping
{
"properties": {
"business_start_time": {
"type" : "date",
"format": "yyyy/MM/dd HH:mm"
},
"business_end_time": {
"type" : "date",
"format": "yyyy/MM/dd HH:mm"
}
}
}
接下来进行店铺注册。
POST /restaurants/_doc
{
"name": "太平洋に浮かぶレストラン",
"business_start_time": "2019/12/22 17:00",
"business_end_time": "2019/12/22 20:00"
}
请确认地图信息。
GET /restaurants/_mapping
按照计划,”business_start_time” 和 “business_end_time” 的类型已被设定为日期。
"business_end_time" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm"
},
"business_start_time" : {
"type" : "date",
"format" : "yyyy/MM/dd HH:mm"
}
如果你尝试搜索18:00还在营业的商店,你可以使用bool和must来进行与搜索。
GET /restaurants/_search
{
"query": {
"bool": {
"must": [
{ "range" : { "business_start_time" : { "lte" : "2019/12/22 18:00" } } },
{ "range" : { "business_end_time" : { "gte" : "2019/12/22 18:00" } } }
]
}
}
}
我们能够获得一个在太平洋上开放的餐厅,按照预期,营业时间为12/22的17:00至20:00。
"hits" : [
{
"_index" : "restaurants",
"_type" : "_doc",
"_id" : "-ieSDG8Br1D6GrZbKNrv",
"_score" : 2.0,
"_source" : {
"name" : "太平洋に浮かぶレストラン",
"business_start_time" : "2019/12/22 17:00",
"business_end_time" : "2019/12/22 20:00"
}
}
]
总结
只需这些基本操作就可以将其掌握!当想要进行更复杂的搜索时,可以参考官方文件,应该就可以做到。
明天是@tsun3先生的《不可怕的JavaScript》。请期待!