2012-01-18 5 views
10

Sto cercando di passare da Solr a ES. Una delle cose che non riesco a trovare informazioni è se ES mi consente di definire i filtri di esclusione durante la sfaccettatura.Elasticsearch: escludendo i filtri mentre sono possibili le sfaccettature? (come in Solr)

Ad esempio si consideri producttype con i valori: A,B,C quale voglio sfaccettare su (vale a dire: spettacolo non conta). Considerare anche che la query è vincolata a producttype: A.

In questo caso, Solr mi consente di specificare che voglio escludere la contraint producttype: A dall'impatto della sfaccettatura su producttype. IOW, visualizza conta su producttype come se il vincolo producttype: A non sia stato applicato.

Come fare questo in Solr veda: http://wiki.apache.org/solr/SimpleFacetParameters> Tagging ed escludendo Filtri

Esiste un modo per fare questo in elasticsearch?

risposta

13

Sì, è possibile.

Mentre è possibile utilizzare i filtri all'interno della query DSL, l'API di ricerca accetta anche un parametro di livello superiore filter, che viene utilizzato per filtrare i risultati della ricerca DOPO che le faccette sono state calcolate.

Ad esempio:

1) In primo luogo, creare l'indice, e perché si vuole product_type essere trattato come un enum, impostarlo per essere not_analyzed:

curl -XPUT 'http://127.0.0.1:9200/my_index/?pretty=1' -d ' 
{ 
    "mappings" : { 
     "product" : { 
     "properties" : { 
      "product_type" : { 
       "index" : "not_analyzed", 
       "type" : "string" 
      }, 
      "product_name" : { 
       "type" : "string" 
      } 
     } 
     } 
    } 
} 
' 

2) Indice alcuni documenti (nota, Doc 3 ha un diverso product_name):

curl -XPUT 'http://127.0.0.1:9200/my_index/product/1?pretty=1' -d ' 
{ 
    "product_type" : "A", 
    "product_name" : "foo bar" 
} 
' 
curl -XPUT 'http://127.0.0.1:9200/my_index/product/2?pretty=1' -d ' 
{ 
    "product_type" : "B", 
    "product_name" : "foo bar" 
} 
' 
curl -XPUT 'http://127.0.0.1:9200/my_index/product/3?pretty=1' -d ' 
{ 
    "product_type" : "C", 
    "product_name" : "bar" 
} 
' 

3) effettuare una ricerca per i prodotti il ​​cui nome contiene 012.380.815,457 mila(che esclude doc 3 e quindi product_typeC), calcolare le sfaccettature per product_type per tutti i documenti che hanno foo nel product_name, quindi filtrare i risultati della ricerca grazie product_type == A:

curl -XGET 'http://127.0.0.1:9200/my_index/product/_search?pretty=1' -d ' 
{ 
    "query" : { 
     "text" : { 
     "product_name" : "foo" 
     } 
    }, 
    "filter" : { 
     "term" : { 
     "product_type" : "A" 
     } 
    }, 
    "facets" : { 
     "product_type" : { 
     "terms" : { 
      "field" : "product_type" 
     } 
     } 
    } 
} 
' 

# { 
# "hits" : { 
#  "hits" : [ 
#   { 
#    "_source" : { 
#    "product_type" : "A", 
#    "product_name" : "foo bar" 
#    }, 
#    "_score" : 0.19178301, 
#    "_index" : "my_index", 
#    "_id" : "1", 
#    "_type" : "product" 
#   } 
#  ], 
#  "max_score" : 0.19178301, 
#  "total" : 1 
# }, 
# "timed_out" : false, 
# "_shards" : { 
#  "failed" : 0, 
#  "successful" : 5, 
#  "total" : 5 
# }, 
# "facets" : { 
#  "product_type" : { 
#   "other" : 0, 
#   "terms" : [ 
#    { 
#    "count" : 1, 
#    "term" : "B" 
#    }, 
#    { 
#    "count" : 1, 
#    "term" : "A" 
#    } 
#   ], 
#   "missing" : 0, 
#   "_type" : "terms", 
#   "total" : 2 
#  } 
# }, 
# "took" : 3 
# } 

4) Eseguire una ricerca per foo nel product_name, ma calcolare sfaccettature per tutti i prodotti nell'indice, specificando il parametro global:

# [Wed Jan 18 17:15:09 2012] Protocol: http, Server: 192.168.5.10:9200 
curl -XGET 'http://127.0.0.1:9200/my_index/product/_search?pretty=1' -d ' 
{ 
    "query" : { 
     "text" : { 
     "product_name" : "foo" 
     } 
    }, 
    "filter" : { 
     "term" : { 
     "product_type" : "A" 
     } 
    }, 
    "facets" : { 
     "product_type" : { 
     "global" : 1, 
     "terms" : { 
      "field" : "product_type" 
     } 
     } 
    } 
} 
' 

# [Wed Jan 18 17:15:09 2012] Response: 
# { 
# "hits" : { 
#  "hits" : [ 
#   { 
#    "_source" : { 
#    "product_type" : "A", 
#    "product_name" : "foo bar" 
#    }, 
#    "_score" : 0.19178301, 
#    "_index" : "my_index", 
#    "_id" : "1", 
#    "_type" : "product" 
#   } 
#  ], 
#  "max_score" : 0.19178301, 
#  "total" : 1 
# }, 
# "timed_out" : false, 
# "_shards" : { 
#  "failed" : 0, 
#  "successful" : 5, 
#  "total" : 5 
# }, 
# "facets" : { 
#  "product_type" : { 
#   "other" : 0, 
#   "terms" : [ 
#    { 
#    "count" : 1, 
#    "term" : "C" 
#    }, 
#    { 
#    "count" : 1, 
#    "term" : "B" 
#    }, 
#    { 
#    "count" : 1, 
#    "term" : "A" 
#    } 
#   ], 
#   "missing" : 0, 
#   "_type" : "terms", 
#   "total" : 3 
#  } 
# }, 
# "took" : 4 
# } 

AGGIORNAMENTO Per rispondere alla domanda espanso dalla OP:

È inoltre possibile applicare filtri direttamente ad ogni sfaccettatura - questi sono chiamati facet_filters.

esempio simile a prima:

1) Creare l'indice:

curl -XPUT 'http://127.0.0.1:9200/my_index/?pretty=1' -d ' 
{ 
    "mappings" : { 
     "product" : { 
     "properties" : { 
      "color" : { 
       "index" : "not_analyzed", 
       "type" : "string" 
      }, 
      "name" : { 
       "type" : "string" 
      }, 
      "type" : { 
       "index" : "not_analyzed", 
       "type" : "string" 
      } 
     } 
     } 
    } 
} 
' 

2) Indice alcuni dati:

curl -XPUT 'http://127.0.0.1:9200/my_index/product/1?pretty=1' -d ' 
{ 
    "color" : "red", 
    "name" : "foo bar", 
    "type" : "A" 
} 
' 

curl -XPUT 'http://127.0.0.1:9200/my_index/product/2?pretty=1' -d ' 
{ 
    "color" : [ 
     "red", 
     "blue" 
    ], 
    "name" : "foo bar", 
    "type" : "B" 
} 
' 

curl -XPUT 'http://127.0.0.1:9200/my_index/product/3?pretty=1' -d ' 
{ 
    "color" : [ 
     "green", 
     "blue" 
    ], 
    "name" : "bar", 
    "type" : "C" 
} 
' 

3) Ricerca, filtrando su prodotti che hanno sia type == A e color == blue, quindi eseguire sfaccettature su ogni attributo escluso, il filtro "altro":

curl -XGET 'http://127.0.0.1:9200/my_index/product/_search?pretty=1' -d ' 
{ 
    "filter" : { 
     "and" : [ 
     { 
      "term" : { 
       "color" : "blue" 
      } 
     }, 
     { 
      "term" : { 
       "type" : "A" 
      } 
     } 
     ] 
    }, 
    "facets" : { 
     "color" : { 
     "terms" : { 
      "field" : "color" 
     }, 
     "facet_filter" : { 
      "term" : { 
       "type" : "A" 
      } 
     } 
     }, 
     "type" : { 
     "terms" : { 
      "field" : "type" 
     }, 
     "facet_filter" : { 
      "term" : { 
       "color" : "blue" 
      } 
     } 
     } 
    } 
} 
' 

# [Wed Jan 18 19:58:25 2012] Response: 
# { 
# "hits" : { 
#  "hits" : [], 
#  "max_score" : null, 
#  "total" : 0 
# }, 
# "timed_out" : false, 
# "_shards" : { 
#  "failed" : 0, 
#  "successful" : 5, 
#  "total" : 5 
# }, 
# "facets" : { 
#  "color" : { 
#   "other" : 0, 
#   "terms" : [ 
#    { 
#    "count" : 1, 
#    "term" : "red" 
#    } 
#   ], 
#   "missing" : 0, 
#   "_type" : "terms", 
#   "total" : 1 
#  }, 
#  "type" : { 
#   "other" : 0, 
#   "terms" : [ 
#    { 
#    "count" : 1, 
#    "term" : "C" 
#    }, 
#    { 
#    "count" : 1, 
#    "term" : "B" 
#    } 
#   ], 
#   "missing" : 0, 
#   "_type" : "terms", 
#   "total" : 2 
#  } 
# }, 
# "took" : 3 
# } 
+0

Grazie. In questo semplice caso funziona. Che ne dici se ho 2 proprietà, ad esempio 'productcategory' e' color'. Mi piacerebbe sfaccettare su entrambe le proprietà ed escludere qualsiasi set di filtri sulla proprietà su cui sto filtrando. Quindi sfaccettatura su 'productcategory' esclude qualsiasi filtro' categorycategory' mentre sfaccettature su 'color' esclude qualsiasi filtro' color'. Fare sfaccettature globali non funziona in questo caso (credo), dal momento che voglio sfaccettare su 'productcategory' per prendere in considerazione tutti i possibili filtri' color' e viceversa. Mi rendo conto che questa è una domanda diversa tra due. –

+0

Ho ampliato la risposta sopra, per dimostrare come farlo – DrTech

+0

Buono a sapersi sull'esistenza di facet_filters. Ho capito correttamente che la specifica di facet_filters su un facet ha la precedenza sul set di filtri (globali)? Avrei pensato che dovevo impostare 'global: 1' sul facet e dettare il facet per ignorare i filtri impostati a livello globale. –