2012-10-01 7 views
17

Poszukuję sposobu na zrobienie dokładnych dopasowań tablic w wyszukiwaniu elastycznym. Powiedzmy to są moje dokumenty:Dokładne wyszukiwanie w typie obiektu tablicy przy użyciu elasticsearch

{"id": 1, "categories" : ["c", "d"]} 
{"id": 2, "categories" : ["b", "c", "d"]} 
{"id": 3, "categories" : ["c", "d", "e"]} 
{"id": 4, "categories" : ["d"]} 
{"id": 5, "categories" : ["c", "d"]} 

Czy istnieje sposób, aby szukać wszystkich dokumentów, które wszystko dokładnie kategorii „C” i „D” (dokumenty 1 i 5), nie więcej lub mniej?

Jako bonus: Poszukiwanie „jeden z tych” kategorii nadal powinno być również możliwe (na przykład można szukać „c” i dostać 1, 2, 3 i 5)

Wszelkie sprytny sposób rozwiązać ten problem?

Odpowiedz

19

Jeśli masz dyskretny, znany zestaw kategorii, można użyć kwerendy bool:

"bool" : { 
    "must" : { 
     "terms" : { "categories" : ["c", "d"], 
      minimum_should_match : 2 
     } 
    }, 
    "must_not" : { 
     "terms" : { "categories" : ["a", "b", "e"], 
      minimum_should_match : 1 
     } 
    } 
} 

przeciwnym razie prawdopodobnie najprostszy sposób do osiągnięcia tego celu, jak sądzę, jest do przechowywania innego pola służąc jako kategorie słów kluczowych.

{"id": 1, "categories" : ["c", "d"], "categorieskey" : "cd"} 

Coś w tym stylu. Następnie możesz łatwo zapytać z zapytaniem o termin, aby uzyskać dokładnie takie wyniki, jakie chcesz, np .:

term { "categorieskey" : "cd" } 

I nadal możesz wyszukiwać nie tylko, jako;

term { "categories" : "c" } 

Zapytania na dwie kategorie, które muszą być obecne jest dość prosta, ale potem zapobieganie innych potencjalnych kategorię z obecną jest nieco trudniejsze. Możesz to zrobić, prawdopodobnie. Prawdopodobnie chciałbyś napisać zapytanie, aby znaleźć rekordy z obydwoma, a następnie zastosować filtr do niego, eliminując wszelkie rekordy z kategoriami innymi niż określone. To naprawdę nie jest rodzaj poszukiwań, które Lucene jest naprawdę zaprojektowana do obsługi, według mojej wiedzy.

Szczerze mówiąc, mam problem z wymyśleniem dobrego filtra do użycia tutaj. Może być potrzebny filtr skryptów lub filtrowanie wyników po ich pobraniu.

+1

śmieszne, to jest dokładnie to, co mu powiedziałem :) – phoet

+0

@phoet jesteś taki mądry;) – paukul

+0

@femtoRgon dziękuję! niestety to złe wieści :) – paukul

1

Znalazłem rozwiązanie dla naszego przypadku użycia, które wydaje się działać. Opiera się na dwóch filtrach i wiedzy o tym, ile kategorii chcemy dopasować. Korzystamy z filtru pojęć i filtra skryptów, aby sprawdzić rozmiar tablicy. W tym przykładzie marketBasketList jest podobny do wpisu kategorii.

{ 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "match": { 
      "siteId": 4 
      } 
     }, 
     { 
      "match": { 
      "marketBasketList": { 
       "query": [ 
       10, 
       11 
       ], 
       "operator": "and" 
      } 
      } 
     } 
     ] 
    }, 
    "boost": 1, 
    "filter": { 
     "and": { 
     "filters": [ 
      { 
      "script": { 
       "script": "doc['marketBasketList'].values.length == 2" 
      } 
      }, 
      { 
      "terms": { 
       "marketBasketList": [ 
       10, 
       11 
       ], 
       "execution": "and" 
      } 
      } 
     ] 
     } 
    } 
    } 
}