57 votes

Comment rechercher des objets imbriqués avec Elasticsearch

OK, je n'ai pas été capable de résoudre ce problème jusqu'à présent. J'espère que quelqu'un pourra m'éclairer.

Compte tenu des documents ci-dessous, comment puis-je rechercher tous les documents contenant une vidéo dont le titre contient le mot "test" ? J'utilise l'API HTTP. (En fait, comment rechercher des objets imbriqués avec la recherche élastique ? Je sais qu'il doit y avoir des docs, mais je n'ai pas vraiment été capable d'en trouver).

[{
    id:4635,
    description:"This is a test description",
    author:"John",
    author_id:51421,
    video: {
        title:"This is a test title for a video",
        description:"This is my video description",
        url:"/url_of_video"
    }
},
{
    id:4636,
    description:"This is a test description 2",
    author:"John",
    author_id:51421,
    video: {
        title:"This is an example title for a video",
        description:"This is my video description2",
        url:"/url_of_video2"
    }
},
{
    id:4637,
    description:"This is a test description3",
    author:"John",
    author_id:51421,
    video: {
        title:"This is a test title for a video3",
        description:"This is my video description3",
        url:"/url_of_video3"
    }
}]

63voto

dira Points 3498

Vous n'avez pas nécessairement besoin d'imbriquer la vidéo ; vous pouvez la mapper comme un champ normal. Ce qui signifie qu'il stockera

'video:title': "This is a test title for a video3",
'video:description':"This is my video description3",
'video:url':"/url_of_video3"

Et vous pouvez chercher video.title:'test' .

D'après ce que je comprends, les champs imbriqués sont utiles lorsque vous avez plusieurs éléments imbriqués et que vous voulez faire une requête uniquement pour les éléments imbriqués. Par exemple, si vous avez les données suivantes

[{
    id:4635,
    description:"This is a test description",
    author:"John",
    author_id:51421,
    video: [
      {
        title:"This is a test title for a video",
        description:"This is my video description",
        url:"/url_of_video"
      },
      {
        title:"This is an example title for a video",
        description:"This is my video description2",
        url:"/url_of_video2"
      }
    ]
},
{
    id:4637,
    description:"This is a test description3",
    author:"John",
    author_id:51421,
    video: [
      {
        title:"This is a test title for a video3",
        description:"This is my video description3",
        url:"/url_of_video3"
      }
    ]
}]

Si vous cherchez video.title: 'test' and video.description: 'description2' et que la vidéo n'était pas imbriquée, il vous donnera un faux résultat (car test est dans la première vidéo et description2 dans le second, mais dans tous les champs vidéo vous avez les deux).

Dans ce cas, si vous définissez la vidéo comme étant imbriquée, chaque vidéo sera considérée comme une entité distincte et le système recherchera les vidéos individuelles qui répondent à ces conditions. video.title: 'test' and video.description: 'description2' il ne retournera rien, car video.title: 'example' and video.description: 'description2' il retournera un résultat.

40voto

swatkins Points 7623

OK, j'ai finalement trouvé ces pages (j'aurais dû prendre plus de temps pour consulter la documentation avant) et il semble qu'il faille définir la propriété qui contient la vidéo comme type:nested, puis utiliser les requêtes imbriquées.

http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html

http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-filter.html

J'espère que cela aidera quelqu'un à l'avenir.

9voto

Si vous voulez le mettre au format URL Rest API

/_search?pretty&q=video.title:*test*

5voto

Radu Gheorghe Points 474

Pour donner une réponse plus générique :

  • utiliser des objets (non imbriqués) si vous recherchez un champ à la fois . C'est parce qu'en interne, les champs sont aplatis, comme suit :

objects in Elasticsearch

  • utilisez l'option "imbriqué" si vous devez effectuer une recherche dans plusieurs champs. (par exemple title:test AND description:my ), car les objets ne se soucient pas des frontières. Par ailleurs, les champs imbriqués créent des documents Lucene distincts qui sont rapidement réunis grâce au BlockJoin de Lucene :

nested fields in Elasticsearch

  • utiliser les relations parents-enfants (entre différents documents Elasticsearch) si vous recherche dans plusieurs champs et mise à jour fréquente des documents des enfants (car les mises à jour des documents imbriqués mettront à jour l'ensemble). En gros, si vous voulez échanger les performances de la requête contre celles de la mise à jour, puisque la requête s'exécute en deux étapes sous le capot :

Elasticsearch has-child query

Note : les dessins ci-dessus sont tirés du site Web de Sematext. Cours de formation sur Elasticsearch (divulgation : je dispense ces cours).

2voto

tsorn Points 633

Vous pouvez utiliser le .keyword suffixe si le nom de l'objet imbriqué est unique :

{
        'query': {
            'term': {
                'title.keyword': "This is a test title for a video"               
            }
        }
}

Ce qui devrait correspondre à votre premier exemple d'entrée. Notez que le video Le nom de l'objet n'est spécifié nulle part ; cela correspond à tous les objets qui ont un nom d'objet de type title sous-objet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X