martes, 1 de abril de 2014

Búsquedas en Elasticsearch

En este post voy a hacer una recopilación de algunas querys más o menos complejas sobre un índice de Elasticsearch.
En primer lugar, el mapping usado (ficticio) será el siguiente, con un tipo película donde tenemos varios campos de distintos tipos: cadenas de caracteres, números, un array de enteros y otro de objetos. La generación del mapping, modificada, se realizó a partir del índice de un modelo en Rails, como explico en el post sobre integrar Elasticsearch en Ruby.

{
  "pelicula":{
    "index_analyzer":"default_index",
    "dynamic_templates":[
      {
        "string_template":{
          "mapping":{
            "type":"multi_field",
            "fields":{
              "analyzed":{
                "index":"analyzed",
                "type":"string"
              },
              "{name}":{
                "index":"not_analyzed",
                "type":"string"
              }
            }
          },
          "match":"*",
          "match_mapping_type":"string"
        }
      }
    ],
    "properties":{
      "presupuesto":{
        "type":"float"
      },
      "imdb":{
        "type":"string",
        "fields":{
          "imdb_sort":{
            "type":"string",
            "index":"not_analyzed"
          }
        }
      },
      "categoria":{
        "type":"string",
        "analyzer":"keyword"
      },
      "duracion":{
        "type":"long"
      },
      "bn":{
        "type":"boolean"
      },
      "actores":{
        "type":"long",
        "index_name":"actor"
      },
      "titulo":{
        "type":"string",
        "fields":{
          "titulo_sort":{
            "type":"string",
            "index":"not_analyzed"
          }
        }
      },
      "premios":{
        "type":"nested",
        "properties":{
          "fecha":{
            "type":"date",
            "format":"dateOptionalTime"
          },
          "actor":{
            "type":"long"
          },
          "nombre":{
            "type":"string",
            "analyzer":"keyword"
          }
        }
      }
    }
  }
}

Un par de comentarios sobre el mapping.
En los campos tipo String sobre los que vamos a tener que realizar operaciones tanto de filtrado como de ordenación, tendremos que convertir el campo en un multifield, de modo que se duplique. Así, la ordenación se realizará sobre el campo not analyzed, y el filtrado sobre el analyzed.
También otra característica de los campos String es que elasticsearch realizará un análisis stemming dependiendo del idioma. En algunos campos querremos evitarlo, como en identificadores tipo cadena. Para ello usaremos el analyzer tipo keyword.