Slide 1

Slide 1 text

@DerekB_WI Location Based Searching with ElasticSearch

Slide 2

Slide 2 text

@DerekB_WI ElasticSearch • Apache Lucene • REST calls • SDKs in many languages • Read optimized

Slide 3

Slide 3 text

@DerekB_WI BELK Stack • Beats - Ingests data streams • Elasticsearch - You know for search • Logstash - Prebuilt dashboard for visualizing logs • Kibana - Browser based client

Slide 4

Slide 4 text

@DerekB_WI Running • AWS - prebuilt • Hosted by Elastic • Install on OS • Docker *

Slide 5

Slide 5 text

@DerekB_WI What Are We Building Today?

Slide 6

Slide 6 text

@DerekB_WI Project • Search nearby locations • Add locations • Comment on existing locations • API

Slide 7

Slide 7 text

@DerekB_WI PHP Client $ composer require elasticsearch/elasticsearch:7.4.*

Slide 8

Slide 8 text

@DerekB_WI docker-compose.yml version: '3'
 services:
 elasticsearch:
 image: docker.elastic.co/elasticsearch/elasticsearch:6.3.2
 environment:
 - cluster.name=docker-cluster
 - bootstrap.memory_lock=true
 - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
 ulimits:
 memlock:
 soft: -1
 hard: -1
 ports:
 - "9200:9200"
 kibana:
 image: docker.elastic.co/kibana/kibana:6.3.2
 ports:
 - "5601:5601"

Slide 9

Slide 9 text

@DerekB_WI How is it stored? • Document - A JSON document for each data element • Index - A grouping of documents with similar structure • Mapping - Defines what is contained in document

Slide 10

Slide 10 text

Define our data

Slide 11

Slide 11 text

Define our data

Slide 12

Slide 12 text

@DerekB_WI Data Types • Text - Content is indexed and searchable • Keyword - Fixed content, think lookup table • Geo-point - latitude/longitude • Geo-shape - Define a polygon • long, integer, short, byte, double, float, half_float, scaled_floa t, date, date_nanos, boolean, binary • More at https://www.elastic.co/guide/en/elasticsearch/ reference/current/mapping-types.html

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

@DerekB_WI Queries GET location-list/location/_search
 {
 "query": {
 "match_all": {}
 }
 }

Slide 15

Slide 15 text

@DerekB_WI Queries GET location-list/location/_search
 {
 "query": {
 "match": {"name": "Big River"}
 }
 }

Slide 16

Slide 16 text

@DerekB_WI

Slide 17

Slide 17 text

@DerekB_WI Queries GET location-list/location/_search
 {
 "query": {
 "bool": {
 "filter": {
 "term": {"feature_class": "L"}
 }
 }
 }
 } https://www.geonames.org/export/codes.html

Slide 18

Slide 18 text

@DerekB_WI Queries GET location-list/location/_search
 {
 "query": {
 "bool": {
 "must":{
 "match": {"name":"Little Park"}
 },
 "filter": {
 "term": {"feature_class": "L"}
 }
 }
 }
 }

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

@DerekB_WI Aggregations GET location-list/location/_search
 {
 "size": 0,
 "aggs": {
 "uniq_feature": {
 "terms": {"field":"feature_class"}
 }
 }
 }

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

@DerekB_WI Benefits? • Fast - 2.4 mil rows in 15ms • Search within text • Other search types, geo, more like this

Slide 23

Slide 23 text

@DerekB_WI Load Data public function addLocation(Location $location)
 {
 $this->locations[] = $location;
 
 if (count($this->locations) >= 1000)
 {
 $this->repository
 ->bulkInsert('location-list', 'location', 
 $this->prepareBulkJson($this->locations)); $this->locations = [];
 } }

Slide 24

Slide 24 text

@DerekB_WI Load Data private function prepareBulkJson()
 {
 return array_map(function($location) {
 return [
 'geonameid' => $location->geonameid,
 'name' => $location->name,
 'asciiname' => $location->asciiname,
 'alternatenames' => $location->alternatenames,
 'location_point' => $location->latitude . ", " $location->longitude,
 'feature_class' => $location->featureClass,
 'feature_code' => $location->featureCode,
 'elevation' => $location->elevation,
 'timezone' => $location->timezone
 ];
 }, $this->locations);


Slide 25

Slide 25 text

@DerekB_WI Load Data public function bulkInsert($indexName, $indexType, $data_lines) { $client = ClientBuilder::create() ->setHosts(['127.0.0.1:9200']) ->build(); $json_body = []; foreach ($data_lines as $line) { $json_body[] = ['index' => [ '_index' => $indexName, '_type' => $indexType ] ]; $json_body[] = $line; } $responses = $client->bulk(['body' => $json_body]); }

Slide 26

Slide 26 text

@DerekB_WI Load Data public function bulkInsert($indexName, $indexType, $data_lines) { $client = ClientBuilder::create() ->setHosts(['127.0.0.1:9200']) ->build(); $json_body = []; foreach ($data_lines as $line) { $json_body[] = ['index' => ['_index' => $indexName, '_type' => $indexType] ]; $json_body[] = $line; } $responses = $client->bulk(['body' => $json_body]); }

Slide 27

Slide 27 text

@DerekB_WI Load Data public function bulkInsert($indexName, $indexType, $data_lines) { $client = ClientBuilder::create() ->setHosts(['127.0.0.1:9200']) ->build(); $json_body = []; foreach ($data_lines as $line) { $json_body[] = ['index' => ['_index' => $indexName, '_type' => $indexType] ]; $json_body[] = $line; } $responses = $client->bulk(['body' => $json_body]); }

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

@DerekB_WI Add to Mapping

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content