首次使用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》。请期待!

广告
将在 10 秒后关闭
bannerAds