2012-10-01 16 views
17

Estoy buscando una manera de hacer exacta matriz coincide en la búsqueda elástica. Digamos que estos son mis documentos:Búsqueda exacta en el tipo de objeto de matriz usando 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"]} 

¿Hay una manera de buscar todas de documento que tienen exactamente las categorías "C" y "D" (documentos 1 y 5), no más o menos?

Como beneficio adicional: La búsqueda de "una de estas" categorías debería ser posible también (por ejemplo, usted podría buscar "c" y obtener 1, 2, 3 y 5)

Cualquier forma inteligente de abordar este problema?

Respuesta

19

Si usted tiene un discreto conjunto conocido de las categorías, se podría utilizar una consulta bool:

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

De lo contrario, probablemente la mejor forma de lograr esto, creo, es la de almacenar otro campo que sirve como una categorías palabra clave

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

Algo así. Posteriormente, se podría fácilmente consulta con una consulta término precisamente por los resultados que desea, como:

term { "categorieskey" : "cd" } 

Y todavía se puede buscar de forma no exclusiva, como;

term { "categories" : "c" } 

Consulta para dos categorías que deben estar presentes tanto es bastante fácil, pero entonces la prevención de cualquier otra categoría potenciales de estar presente es un poco más difícil. Podrías hacerlo, probablemente. Probablemente desee escribir una consulta para buscar registros con ambos, luego aplique un filtro eliminando los registros con categorías distintas a las especificadas. No es realmente un tipo de búsqueda que Lucene está realmente diseñado para manejar, que yo sepa.

Honestamente estoy teniendo problemas para encontrar un buen filtro para usar aquí. Es posible que necesite un filtro de scripts o puede filtrar los resultados una vez recuperados.

+1

divertido, eso es exactamente lo que le dije :) – phoet

+0

@phoet que tan inteligente;) – paukul

+0

@femtoRgon gracias! desafortunadamente esas son malas noticias :) – paukul

1

Encontré una solución para nuestro caso de uso que parece funcionar. Se basa en dos filtros y el conocimiento de la cantidad de categorías con las que queremos comparar. Hacemos uso de un filtro de términos y un filtro de scripts para verificar el tamaño de la matriz. En este ejemplo, marketBasketList es similar a su entrada de categorías.

{ 
    "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" 
      } 
      } 
     ] 
     } 
    } 
    } 
} 
Cuestiones relacionadas