49

好的,到目前为止,我还无法弄清楚这一点。希望有人能提供一些见解。

鉴于以下文件,我将如何搜索视频标题中包含“测试”的视频的所有文件?我正在使用 HTTP API。 (基本上,您如何使用弹性搜索来搜索嵌套对象?我知道那里肯定有文档,但我真的找不到任何文档。)

[{
    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"
    }
}]
4

6 回答 6

59

您不一定需要嵌套视频;您可以将其映射为普通字段。这意味着它将存储

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

您可以搜索video.title:'test'.

据我所知,当您有多个嵌套项目并且您只想对嵌套项目进行查询时,嵌套字段很有用。例如,拥有这些数据

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

如果您要搜索video.title: 'test' and video.description: 'description2',并且 video 没有嵌套,它会给您一个虚假的结果(因为test在第一个视频和description2第二个视频中,但在所有视频字段中您都拥有)。

在这种情况下,如果您将视频映射为嵌套,它会记住每个视频作为一个单独的实体,并将搜索符合这些条件的单个视频,因此video.title: 'test' and video.description: 'description2'它不会返回任何内容,因为video.title: 'example' and video.description: 'description2'它会返回一个结果。

于 2012-02-10T13:54:31.823 回答
40

好的,我终于找到了这些页面(应该事先花更多时间阅读文档),似乎我们将保存视频的属性设置为 type:nested,然后使用嵌套查询。

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

希望这对未来的人有所帮助。

于 2011-11-15T19:04:40.163 回答
8

如果你想把它放在 Rest API URL 格式

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

于 2018-05-18T05:35:43.057 回答
3

.keyword如果嵌套对象的名称是唯一的,则可以使用后缀:

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

哪个应该与您的第一个示例条目匹配。请注意,video没有在任何地方指定对象名称;这匹配具有title子对象的所有对象。

于 2019-03-25T14:58:14.713 回答
0

架构是:

  private schema = {
    id: {
      type: 'integer',
    },
    name: {
      type: 'text',
    },
    tags: {
      type: 'nested',
      properties: {
        id: {
          type: 'integer',
        },
        name: {
          type: 'keyword',
          normalizer: 'useLowercase',
        },
      },
    },
  }

文档结构是

id: 38938
name: "summer fruits"
tags:[
   {
    id : 73
    name: "Grapes"
   },
  {
    id : 74
    name: "Pineapple"
   }
]

搜索查询:

    const { tags } = req.body;

    const { body } = await elasticWrapper.client.search({
        index: ElasticIndexs.Fruits,
        pretty: true,
        filter_path: 'hits.hits._source*',
        body: {
          query: {
            bool: {
              must: tags.map((ele: { name: string }) => {
                return {
                  nested: {
                    path: 'tags',
                    query: {
                      match: {
                        'tags.name': ele.name,
                      },
                    },
                  },
                };
              }),
            },
          },
        },
      });
于 2021-07-24T14:47:50.210 回答
0

给出更通用的答案:

  • 如果一次搜索一个字段,请使用对象(无嵌套)。这是因为在内部,字段被展平,如下所示:

Elasticsearch 中的对象

  • 如果您需要在多个字段中搜索(例如title:test AND description:my),请使用嵌套,因为对象不关心边界。同时,嵌套字段在后台创建单独的 Lucene 文档,这些文档通过 Lucene 的 BlockJoin 快速连接:

Elasticsearch 中的嵌套字段

  • 如果您在多个字段中搜索并经常更新子文档(因为嵌套文档的更新将更新整个集成),请使用父子关系(在不同的 Elasticsearch 文档之间)。基本上,如果您想用查询性能换取更新性能,因为查询在后台分两步运行:

Elasticsearch 有子查询

注意:上图来自 Sematext 的Elasticsearch 培训课程(披露:我提供这些课程)。

于 2021-09-15T14:54:39.943 回答