Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ElasticSearch In Action - PHPNW15

Thijs Feryn
October 04, 2015

ElasticSearch In Action - PHPNW15

Slides from my ElasticSearch talk at PHP North West Conference 2015 In Manchester (UK)

Thijs Feryn

October 04, 2015
Tweet

More Decks by Thijs Feryn

Other Decks in Technology

Transcript

  1. Elasticsearch
    in action
    By Thijs Feryn

    View Slide

  2. This is my
    135th talk

    View Slide

  3. 2010

    View Slide

  4. 2011

    View Slide

  5. 2012

    View Slide

  6. Thank you

    View Slide

  7. Explain in 1 slide

    View Slide

  8. •Full-text search database
    •NoSQL database
    •Analytics engine
    •Written in Java
    •Lucene based ( ~Solr)
    •Inverted indices
    •Easy to scale (~Elastic)
    •RESTFul interface (HTTP/JSON)
    •Schemaless
    •Real-time
    •ELK stack

    View Slide

  9. Still with me?

    View Slide

  10. Hi, I’m Thijs

    View Slide

  11. I’m
    @ThijsFeryn
    on Twitter

    View Slide

  12. I’m an
    Evangelist
    At

    View Slide

  13. I’m a
    at
    board member

    View Slide

  14. CFP open until
    October 14th

    View Slide

  15. https://joind.in/talk/view/15442
    I need
    feedback

    View Slide

  16. https://www.elastic.co/
    downloads/elasticsearch

    View Slide

  17. {  
       "status"  :  200,  
       "name"  :  "War  V",  
       "cluster_name"  :  "elasticsearch",  
       "version"  :  {  
           "number"  :  "1.5.2",  
           "build_hash"  :  
    "62ff9868b4c8a0c45860bebb259e21980778ab1c",  
           "build_timestamp"  :  "2015-­‐04-­‐27T09:21:06Z",  
           "build_snapshot"  :  false,  
           "lucene_version"  :  "4.10.4"  
       },  
       "tagline"  :  "You  Know,  for  Search"  
    }
    http://localhost:9200

    View Slide

  18. RDBMS Elasticsearch
    Database
    Table
    Row
    Index
    Type
    Document

    View Slide

  19. View Slide

  20. POST  /my-­‐index  
    {"acknowledged":true}  
    POST/my-­‐index/my-­‐type  
    {  
       "key"  :  "value",  
       "date"  :  "2015-­‐05-­‐10",  
       "counter"  :  1,  
       "tags"  :  ["tag1","tag2","tag3"]  
    }  
    {  
         "_index":  "my-­‐index",  
         "_type":  "my-­‐type",  
         "_id":  "AU089olr9oI99a_rK9fi",  
         "_version":  1,  
         "created":  true  
    }
    CREATE  DATABASE  my-­‐index
    INSERT  INTO  my-­‐index.my-­‐type  (key,date,counter,tags)    
    VALUES  ("value","2015-­‐05-­‐10",1,"tag1,tag2,tag3")
    Confirmation

    View Slide

  21. GET/my-­‐index/my-­‐type/AU089olr9oI99a_rK9fi?pretty  
    {  
         "_index":  "my-­‐index",  
         "_type":  "my-­‐type",  
         "_id":  "AU089olr9oI99a_rK9fi",  
         "_version":  1,  
         "found":  true,  
         "_source":  {  
               "key":  "value",  
               "date":  "2015-­‐05-­‐10",  
               "counter":  1,  
               "tags":  [  
                     "tag1",  
                     "tag2",  
                     "tag3"  
               ]  
         }  
    }
    Retrieve
    document by
    id
    Document &
    meta data
    SELECT  *    
    FROM  my-­‐index.my-­‐type  
    WHERE  
    id="AU089olr9oI99a_rK9fi"

    View Slide

  22. GET  /my-­‐index/_mapping?pretty  
    {  
         "my-­‐index":  {  
               "mappings":  {  
                     "my-­‐type":  {  
                           "properties":  {  
                                 "counter":  {  
                                       "type":  "long"  
                                 },  
                                 "date":  {  
                                       "type":  "date",  
                                       "format":  "dateOptionalTime"  
                                 },  
                                 "key":  {  
                                       "type":  "string"  
                                 },  
                                 "tags":  {  
                                       "type":  "string"  
                                 }  
                           }  
                     }  
               }  
         }  
    }
    Schemaless?
    Not really …
    “Guesses”
    mapping on
    insert

    View Slide

  23. Explicit mapping
    … using actual data

    View Slide

  24. mysql>  desc  catalog_product_flat_1;  
    +-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐+  
    |  Field                                                    |  Type                                  |  Null  |  Key  |  Default  |  Extra  |  
    +-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐+-­‐-­‐-­‐-­‐-­‐-­‐-­‐+  
    |  entity_id                                            |  int(10)  unsigned          |  NO      |  PRI  |  NULL        |              |  
    |  attribute_set_id                              |  smallint(5)  unsigned  |  NO      |  MUL  |  0              |              |  
    |  type_id                                                |  varchar(32)                    |  NO      |  MUL  |  simple    |              |  
    |  allow_open_amount                            |  int(11)                            |  YES    |          |  NULL        |              |  
    |  cost                                                      |  decimal(12,4)                |  YES    |          |  NULL        |              |  
    |  created_at                                          |  timestamp                        |  YES    |          |  NULL        |              |  
    |  email_template                                  |  varchar(255)                  |  YES    |          |  NULL        |              |  
    |  enable_googlecheckout                    |  smallint(6)                    |  YES    |          |  NULL        |              |  
    |  giftcard_amounts                              |  decimal(12,4)                |  YES    |          |  NULL        |              |  
    |  giftcard_type                                    |  smallint(5)  unsigned  |  YES    |          |  NULL        |              |  
    |  gift_message_available                  |  smallint(6)                    |  YES    |          |  NULL        |              |  
    |  gift_wrapping_available                |  smallint(6)                    |  YES    |          |  NULL        |              |  
    |  gift_wrapping_price                        |  decimal(12,4)                |  YES    |          |  NULL        |              |  
    |  has_options                                        |  smallint(6)                    |  NO      |          |  0              |              |  
    |  image_label                                        |  varchar(255)                  |  YES    |          |  NULL        |              |  
    |  is_recurring                                      |  smallint(6)                    |  YES    |          |  NULL        |              |  
    |  is_redeemable                                    |  int(11)                            |  YES    |          |  NULL        |              |  
    |  lifetime                                              |  int(11)                            |  YES    |          |  NULL        |              |  
    |  links_exist                                        |  int(11)                            |  YES    |          |  NULL        |              |  
    |  links_purchased_separately          |  int(11)                            |  YES    |          |  NULL        |              |  
    |  links_title                                        |  varchar(255)                  |  YES    |          |  NULL        |              |  
    |  msrp                                                      |  decimal(12,4)                |  YES    |          |  NULL        |              |  
    |  msrp_display_actual_price_type  |  varchar(255)                  |  YES    |          |  NULL        |              |  
    |  msrp_enabled                                      |  smallint(6)                    |  YES    |          |  NULL        |              |  
    |  name                                                      |  varchar(255)                  |  YES    |  MUL  |  NULL        |              |  
    |  news_from_date                                  |  datetime                          |  YES    |          |  NULL        |              |  
    |  news_to_date                                      |  datetime                          |  YES    |          |  NULL        |              |  
    |  open_amount_max                                |  decimal(12,4)                |  YES    |          |  NULL        |              |  
    |  open_amount_min                                |  decimal(12,4)                |  YES    |          |  NULL        |              |  
    |  price                                                    |  decimal(12,4)                |  YES    |  MUL  |  NULL        |              |  
    |  price_type                                          |  int(11)                            |  YES    |          |  NULL        |              |  
    |  price_view                                          |  int(11)                            |  YES    |          |  NULL        |              |  
    |  recurring_profile                            |  text                                  |  YES    |          |  NULL        |              |  
    |  required_options                              |  smallint(5)  unsigned  |  NO      |          |  0              |              |  
    |  shipment_type                                    |  int(11)                            |  YES    |          |  NULL        |              |  
    |  short_description                            |  text                                  |  YES    |          |  NULL        |              |  
    |  sku                                                        |  varchar(64)                    |  YES    |          |  NULL        |              |  
    |  sku_type                                              |  int(11)                            |  YES    |          |  NULL        |              |  
    |  small_image                                        |  varchar(255)                  |  YES    |          |  NULL        |              |  
    |  small_image_label                            |  varchar(255)                  |  YES    |          |  NULL        |              |  
    Magento’s
    flattened product
    table

    View Slide

  25. Import data
    from MySQL to
    ElasticSearch

    View Slide

  26. {  
           "category":  [  
                   "Default  Category",  
                   "Men",  
                   "Shirts"  
           ],  
           "entity_id":  "231",  
           "created_at":  "2013-­‐03-­‐05  06:48:12",  
           "updated_at":  "2013-­‐03-­‐05  09:27:15",  
           "name":  "French  Cuff  Cotton  Twill  Oxford",  
           "price":  "190.0000",  
           "description":  "Made  with  wrinkle  resistant  cotton  twill,  this  French-­‐cuffed  
    luxury  dress  shirt  is  perfect  for  Business  Class  frequent  flyers.",  
           "sku":  "msj000"  
    }
    SELECT  GROUP_CONCAT(distinct  c.name)  as  category,p.entity_id,  p.created_at,  
    p.updated_at,  p.name,  p.price,  p.short_description  as  description,p.sku    
    FROM  catalog_product_flat_1    p  
    JOIN  `catalog_category_product_index`  AS  `cat_index`  ON  
    cat_index.product_id=p.entity_id  
    JOIN  `catalog_category_flat_store_1`  AS  `c`  ON  
    cat_index.category_id=c.entity_id  
    WHERE  cat_index.store_id  =  1  AND  cat_index.visibility=1  
    GROUP  BY  p.name  
    ORDER  BY  p.entity_id

    View Slide

  27. POST  /products  
    {  
           "mappings":  {  
                   "product"  :  {  
                           "_id"  :  {  
                                   "path"  :  "entity_id"  
                           },  
                           "properties"  :  {  
                                   "entity_id"  :  {"type"  :  "integer"},  
                                   "name"  :  {  
                                           "type"  :  "string",    
                                           "index"  :  "not_analyzed",  
                                           "fields"  :  {  
                                                   "raw"  :  {  
                                                           "type"  :  "string",  
                                                           "analyzer":  "english"  
                                                   }  
                                           }  
                                   },  
                                   "description"  :  {  
                                           "type"  :  "string",    
                                           "index"  :  "not_analyzed",  
                                           "fields"  :  {  
                                                   "raw"  :  {  
                                                           "type"  :  "string",  
                                                           "analyzer":  "english"  
                                                   }  
                                           }  
                                   },  
                                   "price"  :  {"type"  :  "double"},  
                                   "sku"  :  {"type"  :  "string",  "index"  :  "not_analyzed"},  
                                   "created_at"  :  {"type"  :  "date",  "format"  :  "YYYY-­‐MM-­‐dd  HH:mm:ss"},  
                                   "updated_at"  :  {"type"  :  "date",  "format"  :  "YYYY-­‐MM-­‐dd  HH:mm:ss"}  ,  
                                   "category"  :  {  
                                           "type"  :  "string",  
                                           "index"  :  "not_analyzed"  
                                   }                                
                           }  
                   }  
           }  
    }
    Explicit
    mapping at
    index creation
    time

    View Slide

  28.      "entity_id"  :  {"type"  :  "integer"},  
         "name"  :  {  
                 "type"  :  "string",    
                 "index"  :  "not_analyzed",  
                 "fields"  :  {  
                         "raw"  :  {  
                                 "type"  :  "string",  
                                 "analyzer":  "english"  
                         }  
                 }  
         },  
         "description"  :  {  
                 "type"  :  "string",    
                 "index"  :  "not_analyzed",  
                 "fields"  :  {  
                         "raw"  :  {  
                                 "type"  :  "string",  
                                 "analyzer":  "english"  
                         }  
                 }  
         },  
         "price"  :  {"type"  :  "double"},  
         "sku"  :  {"type"  :  "string",  "index"  :  "not_analyzed"},  
         "created_at"  :  {"type"  :  "date",  "format"  :  "YYYY-­‐MM-­‐dd  HH:mm:ss"},  
         "updated_at"  :  {"type"  :  "date",  "format"  :  "YYYY-­‐MM-­‐dd  HH:mm:ss"}  ,  
         "category"  :  {  
                 "type"  :  "string",  
                 "index"  :  "not_analyzed"  
         }                                
    Not
    analyzed?
    English
    analyzer?

    View Slide

  29. Analyzed
    vs
    non-analyzed

    View Slide

  30. Full-text
    vs
    exact value

    View Slide

  31. Analyzer
    •Character filters
    •Tokenizers
    •Token filters
    Replaces
    characters
    for analyzed
    text
    Break text
    down into
    terms
    Add/modify/
    delete tokens

    View Slide

  32. Built-in analyzers
    •Standard
    •Simple
    •Whitespace
    •Stop
    •Keyword
    •Pattern
    •Language
    •Snowball
    •Custom
    Standard
    tokenizer
    Lowercase
    token filter
    English
    stop word
    token filter

    View Slide

  33. Set the shape to semi-transparent by calling
    set_trans(5)
    set, the, shape, to, semi, transparent, by, calling,
    set_trans, 5
    set, the, shape, to, semi, transparent, by, calling,
    set, trans
    Set, the, shape, to, semi-transparent, by, calling,
    set_trans(5)
    set, shape, semi, transpar, call, set_tran, 5
    Standard
    Simple
    Whitespace
    English

    View Slide

  34. Building a custom analyzer
    PUT  /my_index  
    {  
       "settings":  {  
           "analysis":  {  
               "char_filter":  {  
                   "&_to_and":  {  
                       "type":  "mapping",  
                       "mappings":  [  "&=>  and  "]  
                   }},  
               "filter":  {  
                   "my_stopwords":  {  
                       "type":  "stop",  
                       "stopwords":  [  "the",  "a"  ]  
                   }},  
                   "analyzer":  {  
                       "my_analyzer":  {  
                           "type":  "custom",  
                           "char_filter":    [  "html_strip",  "&_to_and"  ],  
                           "tokenizer":  "standard",  
                           "filter":  [  "lowercase",  "my_stopwords"  ]  
                           }}  
    }}}

    View Slide

  35. Search

    View Slide

  36. GET  /products/product/_search?pretty  
    {  
         "took":  2,  
         "timed_out":  false,  
         "_shards":  {  
               "total":  1,  
               "successful":  1,  
               "failed":  0  
         },  
         "hits":  {  
               "total":  192,  
               "max_score":  1,  
               "hits":  [  
                     {  
                           "_index":  "products",  
                           "_type":  "product",  
                           "_id":  "231",  
                           "_score":  1,  
                           "_source":  {  
                                 "category":  [  
                                       "Default  Category",  
                                       "Men",  
                                       "Shirts"  
                                 ],  
                                 "entity_id":  "231",  
                                 "created_at":  "2013-­‐03-­‐05  06:48:12",  
                                 "updated_at":  "2013-­‐03-­‐05  09:27:15",  
                                 "name":  "French  Cuff  Cotton  Twill  Oxford",  
                                 "price":  "190.0000",  
                                 "description":  "Made  with  wrinkle  resistant  cotton  
    twill,  this  French-­‐cuffed  luxury  dress  shirt  is  perfect  for  Business  
    Class  frequent  flyers.",  
                                 "sku":  "msj000"  
                           }  
                     },  

    SELECT  *  FROM  
    products.product  

    View Slide

  37. GET  /products/product/_search?pretty  
    POST  /products/product/_search?pretty  
    {  
         
       "query":  {  
           "match_all":  {}  
       }  
    }  
    Search
    “lite” vs full
    query DSL
    SELECT  *  FROM  
    products.product  

    View Slide

  38. GET  /products/product/_search?
    pretty&q=name.raw:Blazer  
    POST  /products/product/_search?pretty  
    {  
       "query":  {  
           "match":  {  
               "name.raw":  "Blazer"  
           }  
       }  
    }   SELECT  *  FROM  
    products.product    
    WHERE    
    name  LIKE  "%Blazer%"
    Search
    “lite” vs full
    query DSL

    View Slide

  39. SELECT  *  FROM  
    products.product    
    WHERE    
    name  =  "Linen  Blazer"
    POST  /products/product/_search?
    pretty  
    {  
       "query":  {  
           "match":  {  
               "name.raw":  "Linen  Blazer"  
           }  
       }  
    }  
    POST  /products/product/_search?
    pretty  
    {  
       "query":  {  
           "filtered":  {  
               "query":  {  
                   "match_all":  {}  
               },  
               "filter":  {  
                   "term":  {  
                       "name":  "Linen  Blazer"  
                   }  
               }  
           }  
       }  
    }
    Matches
    2 products
    Matches 1
    product
    SELECT  *  FROM  
    products.product    
    WHERE    
    name  LIKE  "%Linen%"    
    OR    
    name  LIKE  "%Blazer%"

    View Slide

  40. Filter
    vs
    Query

    View Slide

  41. Filter
    •Does it match? Yes or no
    •When relevance doesn’t matter
    •Faster & cacheable
    •For non-analyzed data
    Query
    •How well does it match?
    •For full-text search
    •On analyzed/tokenized data

    View Slide

  42. Match Query
    Multi Match Query
    Bool Query
    Boosting Query
    Common Terms Query
    Constant Score Query
    Dis Max Query
    Filtered Query
    Fuzzy Like This Query
    Fuzzy Like This Field Query
    Function Score Query
    Fuzzy Query
    GeoShape Query
    Has Child Query
    Has Parent Query
    Ids Query
    Indices Query
    Match All Query
    More Like This Query
    Nested Query
    Prefix Query
    Query String Query
    Simple Query String Query
    Range Query
    Regexp Query
    Span First Query
    Span Multi Term Query
    Span Near Query
    Span Not Query
    Span Or Query
    Span Term Query
    Term Query
    Terms Query
    Top Children Query
    Wildcard Query
    Minimum Should Match
    Multi Term Query Rewrite
    Template Query

    View Slide

  43. And Filter
    Bool Filter
    Exists Filter
    Geo Bounding Box Filter
    Geo Distance Filter
    Geo Distance Range Filter
    Geo Polygon Filter
    GeoShape Filter
    Geohash Cell Filter
    Has Child Filter
    Has Parent Filter
    Ids Filter
    Indices Filter
    Limit Filter
    Match All Filter
    Missing Filter
    Nested Filter
    Not Filter
    Or Filter
    Prefix Filter
    Query Filter
    Range Filter
    Regexp Filter
    Script Filter
    Term Filter
    Terms Filter
    Type Filter

    View Slide

  44. Filter
    examples

    View Slide

  45. POST  /products/product/_search?pretty  
    {  
       "query":  {  
           "filtered":  {  
               "filter":  {  
                   "ids":  {  
                       "values":  [231,234,258]  
                   }  
               }  
           }  
       }  
    }
    SELECT  *  FROM  
    products.product    
    WHERE    
    entity_id  IN  
    (231,234,258)

    View Slide

  46. POST  /products/product/_search?pretty  
    {  
       "query":  {  
           "filtered":  {  
               "filter":  {  
                   "bool":  {  
                       "must":  [  
                           {  
                               "range":  {  
                                   "price":  {  
                                       "gte":  100,  
                                       "lte":  400  
                                   }  
                               }  
                           }  
                       ],  
                       "must_not":  [  
                           {  
                               "term":  {  
                                   "name":  "Convertible  Dress"  
                               }  
                           }  
                       ],  
                       "should":  [  
                           {  
                               "term":  {  
                                   "category":  "Women"  
                               }  
                           },  
                           {  
                               "term":  {  
                                   "category":  "New  Arrivals"  
                               }  
                           }  
                       ]  
                   }  
               }  
           }  
       }  
    }
    SELECT  *  FROM  
    products.product    
    WHERE    
    price  BETWEEN  100  AND  
    400  AND  
    name  !=  "Convertible  
    Dress"  AND  
    (category  =  "Women"  
    OR  category  =  "New  
    Arrivals")

    View Slide

  47. POST  /products/product/_search?pretty  
    {  
       "query":  {  
           "filtered":  {  
               "filter":  {  
                   "prefix":  {  
                       "name":  "Slim"  
                   }  
               }  
           }  
       }  
    }
    SELECT  *  FROM  
    products.product    
    WHERE    
    name  LIKE  "Slim%"

    View Slide

  48. {  
           "filtered"  :  {  
                   "filter"  :  {  
                           "geo_distance_range"  :  {  
                                   "from"  :  "200km",  
                                   "to"  :  "400km",  
                                   "pin.location"  :  {  
                                           "lat"  :  40,  
                                           "lon"  :  -­‐70  
                                   }  
                           }  
                   }  
           }  
    }
    Requires “geo
    point” typed
    field

    View Slide

  49. Relevance

    View Slide

  50. {  
         "took":  1,  
         "timed_out":  false,  
         "_shards":  {  
               "total":  1,  
               "successful":  1,  
               "failed":  0  
         },  
         "hits":  {  
               "total":  2,  
               "max_score":  3.3350093,  
               "hits":  [  
                     {  
                           "_index":  "products",  
                           "_type":  "product",  
                           "_id":  "243",  
                           "_score":  3.3350093,  
                           "fields":  {  
                                 "name":  [  
                                       "Linen  Blazer"  
                                 ]  
                           }  
                     },  
                     {  
                           "_index":  "products",  
                           "_type":  "product",  
                           "_id":  "246",  
                           "_score":  0.5954286,  
                           "fields":  {  
                                 "name":  [  
                                       "Stretch  Cotton  Blazer"  
                                 ]  
                           }  
                     }  
               ]  
         }  
    }
    POST  /products/product/_search?pretty  
    {  
       "fields":  ["name"],    
       "query":  {  
           "match":  {  
               "name.raw":  "Linen  Blazer"  
           }  
       }  
    }
    Hits both
    terms. More
    relevant

    View Slide

  51. {  
         "took":  1,  
         "timed_out":  false,  
         "_shards":  {  
               "total":  1,  
               "successful":  1,  
               "failed":  0  
         },  
         "hits":  {  
               "total":  1,  
               "max_score":  1,  
               "hits":  [  
                     {  
                           "_index":  "products",  
                           "_type":  "product",  
                           "_id":  "243",  
                           "_score":  1,  
                           "fields":  {  
                                 "name":  [  
                                       "Linen  Blazer"  
                                 ]  
                           }  
                     }  
               ]  
         }  
    }
    POST  /products/product/_search?pretty  
    {  
       "query":  {  
           "filtered":  {  
               "query":  {  
                   "match_all":  {}  
               },  
               "filter":  {  
                   "term":  {  
                       "name":  "Linen  Blazer"  
                   }  
               }  
           }  
       }  
    }
    No relevance
    on filters
    Score is
    always 1

    View Slide

  52. POST  /products/product/_search?pretty  
    {  
       "fields":  ["name","description"],    
       "query":  {  
           "bool":  {  
               "must":  [  
                   {  
                       "match":  {  
                           "description.raw":  "suit"  
                       }  
                   }  
               ],  
               "should":  [  
                   {  
                       "match":  {  
                           "name.raw":  "coat"  
                       }  
                   }  
               ]  
           }  
       }  
    }
    Only search
    for “suit”
    Increase
    relevance if name
    contains “coat”

    View Slide

  53. POST  /products/product/_search?pretty  
    {  
       "fields":  ["price","name","description","category"],    
       "query":  {  
           "bool":  {  
               "must":  [  
                   {  
                       "filtered":  {  
                           "filter":  {  
                               "bool":  {  
                                   "must":  [  
                                       {  
                                           "range":  {  
                                               "price":  {  
                                                   "gte":  100,  
                                                   "lte":  400  
                                               }  
                                           }  
                                       },  
                                       {  
                                           "term":  {  
                                               "category":  "Men"  
                                           }  
                                       }  
                                   ]      
                               }  
                           }  
                       }  
                   }  
               ],  
               "should":  [  
                   {  
                       "match":  {  
                           "category":  "New  Arrivals"  
                       }  
                   }                  
               ]  
           }  
       }  
    }
    Increase
    relevance
    Combined
    filters

    View Slide

  54. POST  /products/product/_search?pretty  
    {  
       "query":  {  
           "bool":  {  
               "must":  [  
                   {  
                       "match_all":  {}  
                   }  
               ],    
               "should":  [  
                   {  
                       "match":  {  
                           "description.raw":  {  
                               "query":  "comfort",  
                               "boost":  2  
                           }  
                       }  
                   },  
                   {  
                       "match":  {  
                           "name.raw":  {  
                               "query":  "tee",  
                               "boost":  3  
                           }  
                       }  
                   }                  
               ]  
           }  
       }  
    }
    Increase
    relevance
    Query-
    time
    boosting

    View Slide

  55. Multi index
    multi type

    View Slide

  56. SELECT  *    
    FROM  *.tbl_a*    
    WHERE    
    key  LIKE  ‘%val%’
    •Cross-database queries
    •Wildcard database
    queries
    •Wildcard table queries
    Not
    supported
    in SQL

    View Slide

  57. /_search  
    /products/_search  
    /products/product/_search  
    /products,clients/_search  
    /pro*/_search  
    /pro*,cli*/_search  
    /products/product,invoice/_search  
    /products/pro*/_search  
    /_all/product/_search  
    /_all/product,invoice/_search  
    /_all/pro*/_search  

    View Slide

  58. Multi
    “all the
    things”

    View Slide

  59. Aggregations

    View Slide

  60. Group by on steroids

    View Slide

  61. SELECT  COUNT(category)    
    FROM  products.product  
    GROUP  BY  category  
    Aggregations
    in SQL
    Metric
    Bucket

    View Slide

  62. SELECT  COUNT(category)    
    FROM  products.product  
    GROUP  BY  category  
    POST  /products/product/_search?
    pretty&search_type=count  
     {  
       "aggs":  {  
           "number_of_categories"  :  {  
               "cardinality":  {  
                   "field":  "category"  
               }  
           }  
       }  
    }
    Metric
    Bucket
    Only
    aggs, no
    docs

    View Slide

  63. POST  /products/product/_search?pretty  
     {  
       "fields":  ["category","price","name"],    
       "query":  {  
         "match":  {  
             "name.raw":  "blazer"  
         }  
       },  
       "aggs":  {  
           "avg_price":  {  
               "avg":  {  
                   "field":  "price"  
               }  
           },  
           "min_price"  :  {  
               "min":  {  
                   "field":  "price"  
               }  
           },  
           "max_price"  :  {  
               "max":  {  
                   "field":  "price"  
               }  
           },  
           "number_of_products_per_category"  :  {  
               "terms":  {  
                   "field":  "category",  
                   "size":  10  
               }  
           }  
       }  
    }
    Multi-group
    by
    besides
    query

    View Slide

  64.      "aggregations":  {  
               "min_price":  {  
                     "value":  455  
               },  
               "number_of_products_per_category":  {  
                     "doc_count_error_upper_bound":  0,  
                     "sum_other_doc_count":  0,  
                     "buckets":  [  
                           {  
                                 "key":  "Blazers",  
                                 "doc_count":  2  
                           },  
                           {  
                                 "key":  "Default  Category",  
                                 "doc_count":  2  
                           },  
                           {  
                                 "key":  "Men",  
                                 "doc_count":  2  
                           }  
                     ]  
               },  
               "max_price":  {  
                     "value":  490  
               },  
               "avg_price":  {  
                     "value":  472.5  
               }  
         }
    Aggregation
    output
    Drill
    down
    search

    View Slide

  65. Min Aggregation
    Max Aggregation
    Sum Aggregation
    Avg Aggregation
    Stats Aggregation
    Extended Stats Aggregation
    Value Count Aggregation
    Percentiles Aggregation
    Percentile Ranks Aggregation
    Cardinality Aggregation
    Geo Bounds Aggregation
    Top hits Aggregation
    Scripted Metric Aggregation
    Global Aggregation
    Filter Aggregation
    Filters Aggregation
    Missing Aggregation
    Nested Aggregation
    Reverse nested Aggregation
    Children Aggregation
    Terms Aggregation
    Significant Terms Aggregation
    Range Aggregation
    Date Range Aggregation
    IPv4 Range Aggregation
    Histogram Aggregation
    Date Histogram Aggregation
    Geo Distance Aggregation
    GeoHash grid Aggregation

    View Slide

  66. Managing
    Elasticsearch

    View Slide

  67. Plenty of ways
    … for which we don’t have enough time

    View Slide

  68. Clustering

    View Slide

  69. Single
    node
    2 node
    cluster
    3 node
    cluster

    View Slide

  70. Example config settings
    node.rack:    my-­‐location  
    node.master:  true  
    node.data:  true  
    http.enabled:  true  
    cluster.name:  my-­‐cluster  
    node.name:  my-­‐node  
    index.number_of_shards:  5  
    index.number_of_replicas:  1  
    discovery.zen.minimum_master_nodes:  2

    View Slide

  71. CAP theorem

    View Slide

  72. CAP theorem
    Consistence
    Availability
    Partition tolerance

    View Slide

  73. GET /_cat

    View Slide

  74. GET  /_cat  
    =^.^=  
    /_cat/allocation  
    /_cat/shards  
    /_cat/shards/{index}  
    /_cat/master  
    /_cat/nodes  
    /_cat/indices  
    /_cat/indices/{index}  
    /_cat/segments  
    /_cat/segments/{index}  
    /_cat/count  
    /_cat/count/{index}  
    /_cat/recovery  
    /_cat/recovery/{index}  
    /_cat/health  
    /_cat/pending_tasks  
    /_cat/aliases  
    /_cat/aliases/{alias}  
    /_cat/thread_pool  
    /_cat/plugins  
    /_cat/fielddata  
    /_cat/fielddata/{fields}  
    Non-JSON
    output

    View Slide

  75. GET  /_cat/shards?v  
    index        shard  prirep  state      docs  store  ip                          node      
    my-­‐index  2          r            STARTED        6  7.2kb  192.168.10.142  node3    
    my-­‐index  2          p            STARTED        6  9.5kb  192.168.10.142  node2    
    my-­‐index  0          p            STARTED        4  7.1kb  192.168.10.142  node3    
    my-­‐index  0          r            STARTED        4  4.8kb  192.168.10.142  node2    
    my-­‐index  3          r            STARTED        5  7.1kb  192.168.10.142  node1    
    my-­‐index  3          p            STARTED        5  7.2kb  192.168.10.142  node3    
    my-­‐index  1          p            STARTED        1  2.4kb  192.168.10.142  node1    
    my-­‐index  1          r            STARTED        1  2.4kb  192.168.10.142  node2    
    my-­‐index  4          p            STARTED        5  9.5kb  192.168.10.142  node1    
    my-­‐index  4          r            STARTED        5  9.4kb  192.168.10.142  node3  
    5 shards & a
    single replica
    by default

    View Slide

  76. GET  /_cat/health?
    v&h=cluster,status,node.total,shards,pri,unassign,init  
    cluster      status  node.total  shards  pri  unassign  init    
    mycluster  green                      3          12      6                0        0    
    Cluster health

    View Slide

  77. The ELK stack

    View Slide

  78. View Slide

  79. Logs
    Parse
    & ship
    Store
    Visualize

    View Slide

  80. View Slide

  81. Integrating
    Elasticsearch

    View Slide

  82. It’s REST, deal
    with it!
    Directly
    from
    Javascript?
    Don’t
    forget to
    “restrict”
    access
    AJAX #FTW
    Behind a
    proxy
    No
    backend
    code

    View Slide

  83. Or just use a
    backend API
    PHP Java Perl
    Python
    Ruby
    .NET

    View Slide

  84. Since this is a PHP
    conference …

    View Slide

  85. Composer #FTW
    {  
           "require":  {  
                   "elasticsearch/elasticsearch":  "~1.0"  
           }  
    }
    https://github.com/elastic/elasticsearch-php

    View Slide

  86. require 'vendor/autoload.php';
    $connectionParams['hosts'] = array (
    'elastic001',
    'elastic002',
    'elastic003',
    'elastic004',
    'elastic005',
    );
    $client = new Elasticsearch\Client($connectionParams);
    $searchParams['index'] = 'myIndex';
    $searchParams['type'] = 'myType';
    $searchParams['body'] = '{"from":0,"size":"1000","query":{"filtered":
    {"query":{"match_all":{}},"filter":{"and":[{"range":{"timestamp"
    :
    {"from":"2015-06-22T00:00:00Z","to":"2015-06-22T23:59:59Z"}}}]}}},"so
    rt":[{"timestamp":{"order":"desc"
    }}],"facets":{"resultspread":{"terms":{"field":"result"}}}}';
    $results = $client->search($searchParams);
    echo $results['hits']['hits'][0]["_source"]["rcpt"];

    View Slide

  87. View Slide

  88. https://joind.in/talk/view/15442
    I need
    feedback

    View Slide