2014-08-28 14 views
6

Mam kilka dokument json z następującym formacie: -OR i AND Operatorzy w Elasticsearch zapytania

_source: { 
      userId: "A1A1", 
      customerId: "C1", 
      component: "comp_1", 
      timestamp: 1408986553, 
    } 

Chcę kwerendy dokument na podstawie następujących elementów: -

((userId == currentUserId) OR (customerId== currentCustomerId) OR (currentRole ==ADMIN)) AND component= currentComponent) 

Próbowałem za pomocą SearchSourceBuilder i QueryBuilders.matchQuery, ale nie byłem w stanie umieścić wielu zapytań podrzędnych z operatorem AND i OR.

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
searchSourceBuilder.query(QueryBuilders.matchQuery("userId",userId)).sort("timestamp", SortOrder.DESC).size(count); 

W jaki sposób przeprowadzamy kwerendę elastyczną przy użyciu operatorów OR i AND?

Odpowiedz

24

Myślę, że w tym przypadku najlepszy jest strzał Bool query.

Coś jak:

{ 
    "bool" : { 
     "must" : { "term" : { "component" : "comp_1" } }, 
     "should" : [ 
      { "term" : { "userId" : "A1A1" } }, 
      { "term" : { "customerId" : "C1" } }, 
      { "term" : { "currentRole" : "ADMIN" } } 
     ], 
     "minimum_should_match" : 1 
    } 
} 

Co daje w Javie:

QueryBuilder qb = QueryBuilders 
    .boolQuery() 
    .must(termQuery("component", currentComponent)) 
    .should(termQuery("userId", currentUserId)) 
    .should(termQuery("customerId", currentCustomerId)) 
    .should(termQuery("currentRole", ADMIN)) 
    .minimumShouldMatch("1"); // or .minimumNumberShouldMatch(1) 

W must części są AND s, części should są mniej lub bardziej OR s, oprócz tego, że można określić minimalną numer should s jest zgodny (używając minimum_should_match), domyślnie domyślnie jest to minimum 1 (ale można ustawić wartość 0, co oznacza, że ​​dokument pasujący do nr should warunek również zostanie zwrócony).

Jeśli chcesz zrobić bardziej złożonych zapytań które zakładają zagnieżdżone ANDOR S i S, wystarczy zagnieżdżać zapytań bool wewnątrz must lub should części.

Ponadto, jeśli szukasz dokładnych wartości (identyfikatorów i tym podobnych), możesz użyć wartości term queries instead of match queries, która oszczędza Ci fazę analizy (jeśli te pola są w ogóle analizowane, co niekoniecznie ma sens dla id). Jeśli są one analizowane, nadal możesz to zrobić, ale tylko jeśli wiesz dokładnie, jak przechowywane są twoje warunki (standard analyzer stores them lower cased for instance).

+0

'.minimumShouldMatch' pobiera ciąg tylko jako argument, prawda? – BairDev

+0

@malte Masz rację. W tym przypadku powinno to być 'minimumNumberShouldMatch' z' int' lub 'minimumShouldMatch' z' string'. Poprawione. –

+0

Myślę, że to powinna być akceptowana odpowiedź. +1 – NickGreen

2

Jeśli używasz query_string query, twoje AND i OR będą interpretowane jako takie przez bibliotekę Lucene.

To pozwala szukać

(currentUserId OR currentCustomerId) AND currentComponent 

na przykład. Domyślnie wartości będą wyszukiwane we wszystkich polach.

+0

Ale coś w stylu 'QueryBuilders.queryString (" (userId: "+ currentUserId +" OR customerId: "+ currentCustomerId +" OR currentRole: "+ ADMIN +") ORAZ komponent: "+ currentComponent +") ")' powinien działać w sposób zamierzony . –

+0

z połączonej strony dokumentacji ElasticSearch: "Domyślne pole dla warunków zapytania, jeśli nie określono pola prefiksu. Domyślne są ustawienia indeksu index.query.default_field, które z kolei domyślnie _all." Najwyraźniej ElasticSearch dodaje pole _all w czasie indeksowania, do którego możemy następnie zastosować składnię Lucene. –

Powiązane problemy