2012-01-18 7 views
10

Estoy buscando cambiar de Solr a ES. Una de las cosas sobre las que no puedo encontrar información es si ES me permite definir filtros de exclusión al facetar.Elasticsearch: ¿excluyendo los filtros mientras se faceta? (como en Solr)

Por ejemplo, considere producttype con valores: A,B,C con los que quiero trabajar (es decir, mostrar los conteos). Tenga en cuenta también que la consulta está restringida a producttype: A.

En este caso, Solr me permite especificar que quiero excluir el contraint producttype: A del impacto de facetas en producttype. IOW, muestra cuenta en producttype como si la restricción producttype: A no se hubiera aplicado.

cómo hacer esto en Solr ver: http://wiki.apache.org/solr/SimpleFacetParameters> Etiquetado y excluyendo filtros

¿Hay alguna manera de hacer esto en Elasticsearch?

Respuesta

13

Sí, puedes.

Aunque se puede usar filtros dentro de la DSL consulta, la API de búsqueda también acepta un filter parámetro de nivel superior, que se utiliza para filtrar los resultados de búsqueda después se han calculado las facetas.

Por ejemplo:

1) En primer lugar, crear su índice, y porque quiere product_type ser tratada como una enumeración, ponerlo a ser 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) Índice de algunos documentos (nota, doc 3 tiene una diferente 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) Realizar una búsqueda de productos cuyo nombre contiene foo (que excluye doc 3 y por lo tanto product_typeC), calcular facetas para product_type para todos los documentos que tienen foo en el product_name, a continuación, filtrar los resultados de búsqueda por 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) Realizar una búsqueda de foo en el product_name, pero cálculos de facetas para todos los productos en el índice, especificando el parámetro 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 
# } 

ACTUALIZACIÓN responder a la pregunta expandido desde el OP:

También puede aplicar filtros directamente a cada faceta - estos son llamados facet_filters.

ejemplo similar al anterior:

1) crear el índice:

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) Índice de algunos datos:

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) Buscar, filtrando sobre los productos que contengan las dos type == A y color == blue, luego ejecuta las facetas de cada atributo, excluyendo, el "otro" filtro:

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

Gracias. En este simple caso que funciona. ¿Qué tal si tengo 2 propiedades, por ejemplo, 'productcategory' y' color'. Me gustaría trabajar en ambas propiedades y excluir cualquier conjunto de filtros en la propiedad en la que estoy filtrando. Por lo tanto, las facetas de 'productcategory' excluyen cualquier filtro' productcategory' mientras que faceting en 'color' excluye cualquier filtro' color'. Hacer facetas globales no funciona en este caso (creo), ya que quiero hacer facetas en 'productcategory' para tomar cualquier posible' color'-filters en la cuenta y viceversa. Me doy cuenta de que esta es una pregunta diferente por cierto. –

+0

He ampliado la respuesta anterior para demostrar cómo hacerlo – DrTech

+0

Es bueno saber la existencia de facet_filters. ¿Entiendo correctamente que al especificar 'facet_filters' en una faceta se anula el conjunto de filtros (globales)? Hubiera pensado que necesitaba establecer 'global: 1' en la faceta para dictar la faceta e ignorar los filtros globales. –

Cuestiones relacionadas