2015-01-17 8 views
33

Ho una serie di documenti comefiltro che matrice contiene uno qualsiasi dei determinati valori

{ 
    tags:['a','b','c'] 
    // ... a bunch properties 
} 

Come indicato nel titolo: C'è un modo per filtrare tutti i documenti contenenti una delle date tag utilizzando Nest?

Per esempio, il record di cui sopra sarebbe partita [ 'c', 'd']

O dovrei costruire multipla "o" S manualmente?

risposta

25

Modifica: La parte di bitset di seguito è forse una lettura interessante, ma la risposta in sé è un po 'datata. Alcune di queste funzionalità stanno cambiando in 2.x. Anche Slawek sottolinea in un'altra risposta che la query terms è un modo semplice per ASCIUGARE la ricerca in questo caso. Rifattorizzato alla fine per le migliori pratiche attuali. -nz

Probabilmente si vorrà un Bool Query (o più probabilmente Filter al fianco di un'altra query), con una clausola should.

La query bool ha tre proprietà principali: must, should e must_not. Ognuno di questi accetta un'altra query o una serie di query. I nomi delle clausole sono abbastanza auto-esplicativi; nel tuo caso, la clausola should può specificare un filtro di lista, una corrispondenza con una qualsiasi delle quali restituirà il documento che stai cercando.

Dalla documentazione:

In una query booleana senza must clausole, uno o più should clausole devono corrispondere a un documento. È possibile impostare il numero minimo di clausole dovrebbe corrispondere utilizzando il parametro minimum_should_match.

Ecco un esempio di ciò che quella query Bool potrebbe assomigliare in modo isolato:

{ 
    "bool": { 
    "should": [ 
     { "term": { "tag": "c" }}, 
     { "term": { "tag": "d" }} 
    ] 
    } 
} 

Ed ecco un altro esempio di quella query Bool come filtro all'interno di un general-purpose più Filtered Query:

{ 
    "filtered": { 
    "query": { 
     "match": { "title": "hello world" } 
    }, 
    "filter": { 
     "bool": { 
     "should": [ 
      { "term": { "tag": "c" }}, 
      { "term": { "tag": "d" }} 
     ] 
     } 
    } 
    } 
} 

Sia che si utilizzi Bool come query (ad esempio, per influenzare il punteggio delle partite), sia come filtro (ad esempio, per ridurre i colpi che vengono poi valutati o post-filtrati) è soggettivo, a seconda del proprio equirements.

Generalmente è preferibile utilizzare Bool in favore di uno Or Filter, a meno che non si abbia un motivo per utilizzare E/O/Non (tali motivi esistono). Il blog Elasticsearch ha più informazioni sulle diverse implementazioni di ciascuno e buoni esempi di quando preferisci Bool over And/Or/Not e viceversa.

elasticsearch blog: All About Elasticsearch Filter Bitsets

aggiornamento con una query riscritta ...

Ora, con tutto quello fuori strada, la query terms è una versione essiccatore di tutti i sopra.Fa la cosa giusta rispetto al tipo di query sotto il cofano, si comporta allo stesso modo del bool + should usando le opzioni minimum_should_match, e nel complesso è un po 'più conciso.

Ecco che l'ultima interrogazione refactoring un po ':

{ 
    "filtered": { 
    "query": { 
     "match": { "title": "hello world" } 
    }, 
    "filter": { 
     "terms": { 
     "tag": [ "c", "d" ], 
     "minimum_should_match": 1 
     } 
    } 
    } 
} 
+0

devo compilare ogni clausola manualmente, quindi ... – Olivier

+2

minimum_should_match è ora deprecato –

+0

minimum_should_match non risolverà il problema, se si filtra anche da un altro array, dove è necessario il normale comportamento "o". – Innokenty

35

C'è anche terms query cui si dovrebbe risparmiare un po' di lavoro. Qui esempio da documenti:

{ 
    "terms" : { 
     "tags" : [ "blue", "pill" ], 
     "minimum_should_match" : 1 
    } 
} 

Sotto cofano costruisce booleano dovrebbe. Quindi è fondamentalmente la stessa cosa di sopra ma più breve.

C'è anche un corrispondente terms filter.

Quindi, per riassumere la vostra richiesta potrebbe essere la seguente:

{ 
    "filtered": { 
    "query": { 
     "match": { "title": "hello world" } 
    }, 
    "filter": { 
     "terms": { 
     "tags": ["c", "d"] 
     } 
    } 
    } 
} 

Con maggior numero di tag questo potrebbe fare una bella differenza di lunghezza.

+1

Ho problemi a far funzionare questo. Ti dispiacerebbe verificarlo qui http://stackoverflow.com/questions/32252789/elastic-search-rails-combine-multi-match-and-filter –

+5

'minimum_should_match' è deprecato e fallirà. –

+0

@AinTohvri in realtà in elasticsearch 2.0.1 minimum_should_match funziona ancora e il documento ufficiale non lo segnala come deprecato. – Sinux

Problemi correlati