Consultas anidadas de ElasticSearch: Cómo buscar documentos incrustados

Consultas anidadas de ElasticSearch: Cómo buscar documentos incrustados

  • Orquestación
5 min de lectura Actualizado Nov 16, 2018

Puntos clave: ElasticSearch puede tener problemas con documentos JSON anidados, lo que lleva a resultados de búsqueda incorrectos. Para solucionar esto, Define explícitamente el índice para reconocer estructuras anidadas y mejorar la precisión en la búsqueda al consultar documentos incrustados.

  • Los objetos JSON anidados pueden complicar los resultados de búsqueda en ElasticSearch.
  • La creación explícita de índices está necesaria para consultar con precisión documentos incrustados.

ElasticSearch están molestamente complicado a veces. te puede ejecutar una búsqueda y ejecuta resultados incorrectos y no te son informado de ello. Esto puede ocurrir cuando, por ejemplo, te tienen un documento JSON anidado, es decir, un documento JSON dentro de otro. Esto están porque la consulta Lucene (es decir, ElasticSearch) no tiene comprensión de la jerarquía de objetos en un documento JSON.

El problema de buscar objetos JSON anidados

Para ilustrar el problema y la solución, descarga este programa massAdd.py y cambia la URL para que coincida con tu entorno ElasticSearch. Luego ejecútalo. Después mira los datos cargados. te puede Ve desde los corchetes que están un array JSON. Pero el índice, como vamos a Ve, no refleja eso.

    curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities/_search?pretty}

"_index" : "universities",
        "_type" : "universities",
        "_id" : "428b71b0b935eaf58bdf874c819f263a919da5f3",
        "_score" : 0.0,
        "_source" : {
          "firstName" : "Stephen",
          "classes" : [
            {
              "name" : "French",
              "grades" : 2
            },
            {
              "name" : "French",
              "grades" : 3
            },
            {
              "name" : "French",
              "grades" : 2
            },
            {
              "name" : "physics",
              "grades" : 6
            },
            {
              "name" : "physics",
              "grades" : 5
            }
          ],
          "lastName" : "Shakespeare",
          "school" : "Arizona State University"
        }
      }
    ]
  }

Fíjate que el mapeo de índice no muestra el array JSON. Esto no están porque no son corchetes []. Más bien, la palabra anidada está ausente.

    curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities?pretty

...

"classes" : {
            "properties" : {
              "grades" : {
                "type" : "long"
              },
              "name" : {
                "type" : "text",
                "fields" : {
                  "keyword" : {
                    "type" : "keyword",
                    "ignore_above" : 256
                  }
                }
              }
            }
          },
...

Así que haz una búsqueda usando lo que te crees que sería la forma lógica de encontrar estudiantes que cursen física y que hayan sacado una nota de 1:

    curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities/_search/?pretty=true -d '{
    "query": {
                "bool" : {
                    "must" : [
                    { "match" : {"classes.name" : "physics"} },
                    { "match" : {"classes.grades" :  1} }
                    ]
            }
        }
}'

Produce este resultado incorrecto. Esto están porque Lucene aplana todo el documento y encuentra tanto las clases. Grado 1 como classes.name física.

    {
        "_index" : "universities",
        "_type" : "universities",
        "_id" : "5846c01f90d80448ab087bf4f476cd3f8ab6f683",
        "_score" : 1.621972,
        "_source" : {
          "classes" : [
            {
              "grades" : 2,
              "name" : "physics"
            },
            {
              "grades" : 2,
              "name" : "French"
            },
            {
              "grades" : 3,
              "name" : "physics"
            },
            {
              "grades" : 1,
              "name" : "math"
            }
          ],
          "firstName" : "Stephen",
          "lastName" : "Rowe",
          "school" : "University of South Carolina - Columbia"
        }
      }

Haciendo explícito el índice

te puede Crea un índice en ElasticSearch simplemente cargando datos. Eso lo crea sobre la marcha. Pero te no puedes controlar cómo están se crea el índice si te hacer eso. Así que vamos a Haz la creación del índice explícita y Haz clara que las clases están un array JSON. Primero borra el índice, que también eliminará todos los datos.

    curl -XDELETE http://parisx:9200/universities

Luego Crea un nuevo índice y Haz explícito que clases están un objeto dentro del objeto de la universidad usando "tipo": "anidado". Nota: que no son rellenamos datos universitarios, solo estudiantes. Así que ignora esos campos. (Vamos a utilizar datos universitarios en otra publicación y los usamos en la anterior).

    curl -XPUT --header 'Content-Type: application/json' http://parisx:9200/universities -d '{
    "mappings" : {
      "universities" : {
        "properties" : {
          "Address" : { "type" : "text"},
          "AdminEmail" : { "type" : "text"},
          "AdminName" : { "type" : "text" },
          "AdminPhone" : { "type" : "text" },
          "DapipId" : { "type" : "text" },
          "Fax" : { "type" : "text" },
          "GeneralPhone" : { "type" : "text" },
          "LocationName" : { "type" : "text" },
          "LocationType" : { "type" : "text" },
          "OpeId" : { "type" : "text" },
          "ParentDapipId" : { "type" : "text" },
          "ParentName" :  { "type" : "text" },
          "UpdateDate" : { "type" : "text" },
          "classes" : {
                "type" : "nested",
                "properties" : {
                   "name" : { "type" : "text"},
                   "grades" : { "type" : "integer" }
              }
            },
        "firstName" : { "type" : "text" },
          "lastName" : { "type" : "text" },
          "school" : { "type" : "text" }
            }
          }
        }
}'

Luego carga los datos de nuevo ejecutando massAdd.py de nuevo: Ahora añade los términos anidado y path a la consulta para encontrar a los estudiantes que obtuvieron una nota de 1 en física. El path están el objeto padre en el JSON, que en este caso están clases. Y utiliza classes.name buscar por nombre de clase:

    curl -XGET --header 'Content-Type: application/json' http://parisx:9200/universities/_search/?pretty=true -d '{
    "query": {
        "nested" : {
            "path" : "classes",
            "score_mode" : "avg",
            "query" : {
                "bool" : {
                "must" : [
                    { "match" : {"classes.name" : "physics"} },
                    { "match" : {"classes.grades" : 1} }
                    ]
                }
            }
        }
    }
}'

resulta en el resultado correcto.

    {
        "_index" : "universities",
        "_type" : "universities",
        "_id" : "20ce682e16d0b88487addc9ceba2a695d57692aa",
        "_score" : 2.188588,
        "_source" : {
          "lastName" : "Shakespeare",
          "firstName" : "Julie",
          "classes" : [
            {
              "grades" : 1,
              "name" : "physics"
            },
            {
              "grades" : 6,
              "name" : "math"
            }
          ],
          "school" : "Arizona State University"
        }
      }
    ]

Estas publicaciones son mías y no representan necesariamente la posición, estrategias u opinión de BMC.

Más de Orquestación

¿Te interesa saber más de BMC?

El Brief están nuestro correo mensual sobre el mainframe y la orquestación empresarial: investigación, historias de clientes, noticias de productos, eventos.

Al registrarse para esta oferta te son confirmar que te leído y aceptado la Política de Privacidad de BMC.

Tú te has suscrito a The Brief

El Brief abarca la orquestación de mainframe y empresa—BMC AMI y Control-M—y la investigación de analistas, despliegues de clientes y eventos en ambas áreas.