2011-08-25 4 views
15

Pracowałem z ElasticSearch od kilku miesięcy, ale nadal uważam, że jest skomplikowane, gdy muszę przejść skomplikowane zapytanie.Jak korzystać z parametrów zapytania ElasticSearch (zapytanie DSL) dla wielu typów?

Chcę uruchomić kwerendę, która będzie musiała przeszukać kilka „typów”, a każdy typ ma być przeszukiwane z własnymi „Filtry”, ale trzeba się łączyć „poszukiwanej wyniki”

Na przykład:

Muszę przeszukać dokument "typu użytkownika", który jest moim znajomym i jednocześnie muszę przeszukać dokument "typu obiektu", który mi się podoba, zgodnie z podanym słowem kluczowym.

lub

Zapytanie, zarówno "I" i "NIE" punkt

Przykład zapytania:

$options['query'] = array(
     'query' => array(
      'filtered' => array(
       'query' => array(
        'query_string' => array(
         'default_field' => 'name', 
         'query' => $this->search_term . '*', 
        ), 
       ), 
       'filter' => array(
        'and' => array(
         array(
          'term' => array(
           'access_id' => 2, 
          ), 
         ), 
        ), 

        'not' => array(
         array(
          'term' => array(
           'follower' => 32, 
          ), 
         ), 

         array(
          'term' => array(
           'fan' => 36, 
          ), 
         ), 
        ), 
       ), 
      ), 
     ), 
    ); 

jak to zapytanie ma wyszukiwania użytkownikowi access_id = 2 , ale nie może mieć identyfikatora ID 32 i wentylatora ID 36

ale to nie działa.

Edit: Zmodyfikowane zapytanie

{ 
    "query": { 
    "filtered": { 
     "filter": { 
     "and": [ 
      { 
      "not": { 
       "filter": { 
       "and": [ 
        { 
        "query": { 
         "query_string": { 
         "default_field": "fan", 
         "query": "*510*" 
         } 
        } 
        }, 
        { 
        "query": { 
         "query_string": { 
         "default_field": "follower", 
         "query": "*510*" 
         } 
        } 
        } 
       ] 
       } 
      } 
      }, 
      { 
      "term": { 
       "access_id": 2 
      } 
      } 
     ] 
     }, 
     "query": { 
     "field": { 
      "name": "xyz*" 
     } 
     } 
    } 
    } 
} 

teraz po uruchomieniu tej kwerendy, otrzymuję dwa wyniki, jeden z zwolennik "34,518" & wentylatora: "510", a drugi z wentylatorem: "34", ale nie powinno to być tylko drugie w wyniku.

Jakieś pomysły?

Odpowiedz

14

Możesz zajrzeć na slajdy z prezentacji, którą dałem w tym miesiącu, co wyjaśnia podstawy jak działa DSL zapytanie:

Terms of endearment - the ElasticSearch Query DSL explained

Problem z zapytania jest to, że filtry są zagnieżdżone niepoprawnie. W and i not filtry są na tym samym poziomie, ale filtr not powinny być pod and:

curl -XGET 'http://127.0.0.1:9200/_all/_search?pretty=1' -d ' 
{ 
    "query" : { 
     "filtered" : { 
     "filter" : { 
      "and" : [ 
       { 
        "not" : { 
        "filter" : { 
         "and" : [ 
          { 
           "term" : { 
           "fan" : 36 
           } 
          }, 
          { 
           "term" : { 
           "follower" : 32 
           } 
          } 
         ] 
        } 
        } 
       }, 
       { 
        "term" : { 
        "access_id" : 2 
        } 
       } 
      ] 
     }, 
     "query" : { 
      "field" : { 
       "name" : "keywords to search" 
      } 
     } 
     } 
    } 
} 
' 
+0

Czy filtr "nie" zawsze znajduje się pod filtrem "i" lub właśnie w tym przypadku –

+0

Witam @DrTech, właśnie edytowałem pytanie, proszę sprawdzić. –

+1

Twoje edytowane pytanie wprowadza inne problemy. Sugeruję zapoznanie się z prezentacją, z którą się łączyłem - wyjaśnia różnicę między terminami i tekstem oraz rodzajami zapytań i filtrów, których należy użyć. – DrTech

3

Właśnie próbowałem go z „BOOL”

{ 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "term": { 
      "access_id": 2 
      } 
     }, 
     { 
      "wildcard": { 
      "name": "xyz*" 
      } 
     } 
     ], 
     "must_not": [ 
     { 
      "wildcard": { 
      "follower": "*510*" 
      } 
     }, 
     { 
      "wildcard": { 
      "fan": "*510*" 
      } 
     } 
     ] 
    } 
    } 
} 

To daje poprawną odpowiedź.

ale nie jestem pewien, czy należy go używać w ten sposób?

+2

To zadziała, ale jest strasznie nieefektywne. Klauzula wieloznaczna musi ładować wszystkie terminy, znajdować wszystkie pasujące terminy, a następnie przepisać zapytanie, aby zawierało wszystkie te terminy. To naprawdę może wybuchnąć. Znacznie lepiej jest analizować dane poprawnie w czasie indeksowania, aby można było podzielić wartości na oddzielne warunki, które można dopasować indywidualnie. Być może będziesz musiał skorzystać z analizatora ngram, ale to naprawdę zależy od twoich danych. Spójrz na ten wątek na przykład http://elasticsearch-users.115913.n3.nabble.com/help-needed-with-the-query-tt3177477.html#a3178856 – DrTech

+1

Dzięki @DrTech, jest bardzo dobrze wyjaśniony . +1. I naprawdę powiedziałbym, że powinieneś napisać Pełny Tutorial na ElasticSearch, ponieważ nikt jeszcze tego nie zrobił :) Dzięki –