Pokazywanie postów oznaczonych etykietą range. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą range. Pokaż wszystkie posty

sobota, 28 września 2013

[FullTextSearch] ElasticSearch: Faceting

Terminem Faceting określa się technikę agregowania danych gromadzonych w indeksach ElasticSearch. Wysyłając odpowiednie zapytania możemy pobrać pewne informacje statystyczne na temat dokumentów, jakie przechowujemy. Pierwszy rodzaj statystyki, jaką możemy sobie stworzyć to grupowanie po tokenach utworzonych na danym polu, a następnie zliczenie ilości. Wysyłamy zapytanie...

POST http://localhost:9200/books/book/_search HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 135

{
 "query" : { "match_all" : {} },
 "facets" : {
  "author_facet" : {
   "terms" : {
    "field" : "author"
   }
  }
 }
}

...i w odpowiedzi otrzymujemy:

{
   "took":4,
   "timed_out":false,
   "_shards":{
      "total":5,
      "successful":5,
      "failed":0
   },
   "hits":{
      "total":5,
      "max_score":1.0,
      "hits":[
       (...)
      ]
   },
   "facets":{
      "author_facet":{
         "_type":"terms",
         "missing":0,
         "total":10,
         "other":0,
         "terms":[
            {
               "term":"michio",
               "count":3
            },
            {
               "term":"kaku",
               "count":3
            },
            {
               "term":"roger",
               "count":2
            },
            {
               "term":"penrose",
               "count":2
            }
         ]
      }
   }
}

Dane możemy także agregować definiując zakresy, na przykład

POST http://localhost:9200/books/book/_search HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 246

{
 "query" : { "match_all" : {} },
 "facets" : {
  "ranges_facet_result" : {
   "range" : {
    "field" : "year",
    "ranges" : [
     { "to" : 1995 },
     { "from" : 1995, "to" : 2000 },
     { "from" : 2000 }
    ]
   }
  }
 }
}

Zwrócone nam zostanie więcej informacji niż poprzednio, ponieważ agregujemy po polu typu numerycznego

{
   "took":145,
   "timed_out":false,
   "_shards":{
      "total":5,
      "successful":5,
      "failed":0
   },
   "hits":{
      "total":5,
      "max_score":1.0,
      "hits":[

      ]
   },
   "facets":{
      "ranges_facet_result":{
         "_type":"range",
         "ranges":[
            {
               "to":1995.0,
               "count":2,
               "min":1989.0,
               "max":1993.0,
               "total_count":2,
               "total":3982.0,
               "mean":1991.0
            },
            {
               "from":1995.0,
               "to":2000.0,
               "count":1,
               "min":1995.0,
               "max":1995.0,
               "total_count":1,
               "total":1995.0,
               "mean":1995.0
            },
            {
               "from":2000.0,
               "count":2,
               "min":2004.0,
               "max":2006.0,
               "total_count":2,
               "total":4010.0,
               "mean":2005.0
            }
         ]
      }
   }
}

Powyższe zapytanie możemy także wykonać przy równomiernym rozłożeniu danych (tak jak w histogramie).

POST http://localhost:9200/books/book/_search HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 156

{
 "query" : { "match_all" : {} },
 "facets" : {
  "total_histogram" : {
   "histogram" : {
    "field" : "year",
    "interval" : 5
   }
  }
 }
}

Najwięcej danych do analizy dostarcza nam jednak zapytanie typu statistical.

POST http://localhost:9200/books/book/_search HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 139

{
 "query" : { "match_all" : {} },
 "facets" : {
  "statistical_test" : {
   "statistical" : {
    "field" : "price"
   }
  }
 }
}

ElasticSearch zwraca między innymi zakres, średnią, wariancję, odchylenie standardowe i sumę kwadratów.

{
   "took":55,
   "timed_out":false,
   "_shards":{
      "total":5,
      "successful":5,
      "failed":0
   },
   "hits":{
      "total":5,
      "max_score":1.0,
      "hits":[(...)]
   },
   "facets":{
      "statistical_test":{
         "_type":"statistical",
         "count":5,
         "total":114.67999999999999,
         "min":12.06,
         "max":42.0,
         "mean":22.936,
         "sum_of_squares":3157.3112,
         "variance":105.40214400000013,
         "std_deviation":10.266554631423345
      }
   }
}

piątek, 27 września 2013

[FullTextSearch] ElasticSearch: Query DSL

Zapytania do ElasticSearch wysyłamy REST-owo. Do prostego pobierania dokumentów wystarczą nam sparametryzowane zapytania typu GET. Aby jednak poznać pełnię możliwości ElasticSearch musimy poznać język zapytań DSL, w którym parametry zapytania ustawiamy poprzez załączenie z żądaniem typu POST odpowiedniego obiektu w postaci JSON. ElasticSearch udostępnia wiele rodzajów zapytań. Poniżej ciekawsze z nich.

Term Query

Tego typu zapytania można wykonywać na dwa sposoby. Przy użyciu czasownika GET

http://localhost:9200/books/book/_search?q=title:parallel&pretty=true

lub za pomocą czasownika POST

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 59

{
 "query" : {
  "term" : { "title" : "parallel" }
 }
}

W obu przypadkach otrzymujemy ten sam rezultat

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 809

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.095891505,
    "hits" : [ {
      "_index" : "books",
      "_type" : "book",
      "_id" : "1",
      "_score" : 0.095891505, "_source" : {
 "title": "Parallel Worlds: A Journey Through Creation, Higher Dimensions, and the Future of the Cosmos",
 "author": "Michio Kaku",
 "year": 2006,
 "price": 12.06
}
    }, {
      "_index" : "books",
      "_type" : "book",
      "_id" : "3",
      "_score" : 0.095891505, "_source" : {
 "title": "Hyperspace: A Scientific Odyssey Through Parallel Universes, Time Warps, and the Tenth Dimension",
 "author": "Michio Kaku",
 "year": 1995,
 "price": 16.36
}
    } ]
  }
}

Term Query to takie zapytanie, które zwraca wyniki tylko wtedy, gdy podamy dokładnie słowo, które znajduje się w danym polu. Nie zadziałają tutaj zapytania przedrostowe typu "paral*". Wyniki za każdym razem dostępne będą w tablicy dostępnej pod hits.hits. Pełny dokument zwracany jest w polu _source. Pobieranie tak zagnieżdżonych informacji wydaje się niewygodne, a czasami także niepotrzebnie przesyłany jest cały duży dokument, dlatego możemy podać, które pola nas interesują.

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 92

{
 "fields" : ["title","author"],
 "query" : {
  "term" : { "title" : "parallel" }
 }
}

W rezultacie otrzymamy:

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 797

{
  "took" : 9,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.095891505,
    "hits" : [ {
      "_index" : "books",
      "_type" : "book",
      "_id" : "1",
      "_score" : 0.095891505,
      "fields" : {
        "title" : "Parallel Worlds: A Journey Through Creation, Higher Dimensions, and the Future of the Cosmos",
        "author" : "Michio Kaku"
      }
    }, {
      "_index" : "books",
      "_type" : "book",
      "_id" : "3",
      "_score" : 0.095891505,
      "fields" : {
        "title" : "Hyperspace: A Scientific Odyssey Through Parallel Universes, Time Warps, and the Tenth Dimension",
        "author" : "Michio Kaku"
      }
    } ]
  }
}

Odpytywać można także tylko indeks (bez podawania typu book) oraz wiele indeksów lub wiele typów. Na przykład:

http://localhost:9200/books,books5/book/_search?q=author:kaku&pretty=true

Terms Query

Podajemy kilka wartości, które nie będą analizowane (muszą to być dokładne wartości), oraz opcjonalnie ile z nich musi pasować, aby zwrócony został dany dokument.

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 111

{
 "query" : {
  "terms" : { "title" : ["parallel","hyperspace","worlds"],
  "minimum_match" : 2
  }
 }
}

Match Query

W tym zapytaniu podane wyrażenie zostaje przetworzone przez analizator. A zatem tym razem możemy podawać niepełne wyrazy, na przykład:

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 65

{
 "query" : {
  "match" : { "title" :"para worlds"
  }
 }
}

Zapytanie takie zwróci wyniki. Domyślnie słowa są łączone operatorem OR, można to zmienić w następujący sposób.

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 122

{
 "query" : {
  "match" : {
   "title" : {
    "query" : "parallel worlds",
    "operator" : "and"
   }
  }
 }
}

Match Phrase

Jeżeli chcemy wyszukać frazy składającej się z większej ilości słów, korzystamy z match_phrase, gdzie parametr slop definiuje, ile nieznanych słów może się mieścić pomiędzy podanymi wyrazami.

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 121

{
 "query" : {
  "match_phrase" : {
   "title" : {
    "query" : "parallel worlds",
    "slop" : 1
   }
  }
 }
}

Multi Match

Efekt zapytania typu "Match" możemy uzyskać także na wielu polach dokumentu.

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 131

{
 "query" : { 
  "multi_match" : {
   "query" : "univers michio penrose",
   "fields" : [ "title", "author" ]
  }
 }
}

Identifiers Query

Kiedy dokładnie znamy identyfikatory dokumentów, które chcemy pobrać, korzystamy z tego typu zapytania.

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 73

{
 "query" : {
  "ids" : {
   "values" : [ "1", "4", "5" ]
  }
 }
}

Prefix Query

Wyszukiwanie po przedrostkach.

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 63

{
 "query" : {
  "prefix" : {
   "title" : "uni"
  }
 }
}

Fuzzy Like This Query

Zapytanie, które dopuszcza literówki w podanej frazie.

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 115

{
 "query" : {
  "fuzzy_like_this" : {
   "fields" : ["title", "author"],
   "like_text" : "penrse"
  }
 }
}

Range Query

Podajemy zakresy, przydatne dla wartości numerycznych.

POST http://localhost:9200/books/book/_search?pretty=true HTTP/1.1
User-Agent: Fiddler
content-type: application/json
Host: localhost:9200
Content-Length: 100

{
 "query" : {
  "range" : {
   "year" : {
    "from" : 1990,
    "to" : 2000
   }
  }
 }
}