使用ElasticSearch查询多项嵌套文档

时间:2014-08-20 13:54:43

标签: ruby-on-rails elasticsearch

我是Elasticsearch的新手,我很难理解为什么会做某些事情。我有以下文档结构索引(我在Rails中使用Chewy,但它应该有意义):

class OpportunityLocationsIndex < Chewy::Index
  define_type OpportunityLocation.includes(:opportunity).joins(:opportunity => :company).where(:opportunities => {is_valid: true}) do
    field :location
    field :coordinates, type: 'geo_point'
    field :opening_status

    field :opportunity, type: 'object' do
      field :name, :summary
      field :opportunity_count, value: ->(o) { o.total_positions }

      field :company, type: 'object' do
        field :name
        field :slug
        field :industry

        field :company_path, value: ->(c) { "/companies/" + c.slug }
        field :logo_image, value: ->(c) { c.logo_image.url(:medium) }
        field :logo_image_grey, value: ->(c) { c.logo_image.url(:greyscale) }
      end
    end
  end
end

现在,我想要获取所有位于“Johannesburg,Gauteng,South Africa”的文档,我会运行以下查询:

GET _search
{
    "query": {
        "match": {
           "location": "Johannesburg, Gauteng, South Africa"
        }
    }
}

哪会吐出以下内容。

  {
     "took": 7,
     "timed_out": false,
     "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
     },
     "hits": {
        "total": 13,
        "max_score": 1.6014341,
        "hits": [
           {
              "_index": "opportunity_locations",
              "_type": "opportunity_location",
              "_id": "56",
              "_score": 1.6014341,
              "_source": {
                 "location": "Johannesburg, Gauteng, South Africa",
                 "coordinates": "28.0473051, -26.2041028",
                 "opening_status": "closed",
                 "opportunity": {
                    "name": "Bentley Test Opportunity",
                    "summary": "Engineering at Bentley provides some unique and interesting challenges. The Interior Systems engineers...",
                    "opportunity_count": 6,
                    "company": {
                       "name": "Bentley Motors",
                       "slug": "bentley-motors",
                       "industry": "Automobile / Mechanical Engineering",
                       "company_path": "/companies/bentley-motors",
                       "logo_image": "/public/system/companies/logo_images/000/000/008/medium/bentley_logo_desktop_wallpaper-normal.jpg?1397906812",
                       "logo_image_grey": "/public/system/companies/logo_images/000/000/008/greyscale/bentley_logo_desktop_wallpaper-normal.jpg?1397906812"
                    }
                 }
              }
           },
           { etc. }
        ]
     }
  }

是的,这样才有效并且有意义。现在,如果我想获得公司名称为“Bentley Motors”或“BMW”的所有文件,我会尝试以下操作:

GET _search
{
    "query": {
        "terms": {
           "opportunity.company.name": [
              "Bentley Motors",
              "BMW"
           ]
        }
    }
}

返回零结果。我做错了什么?

1 个答案:

答案 0 :(得分:3)

这与您如何索引数据以及如何查询数据有关。

您的第一个请求使用匹配查询,该查询足够聪明,可以确定是否必须分析您的数据,具体取决于您如何映射文档类型。

您的第二个请求使用术语查询,该查询不使用任何分析器,并在倒排索引中搜索完全相同的值。

例如,如果使用默认映射索引字符串TEST

  • 使用TEST的字词查询将不会输出结果
  • TEST的匹配查询将返回您的文档,因为它将以与索引时相同的方式分析文本。

在您的情况下,当您为文档编制索引时,使用标准分析器分析了此字段值,该分析器已将您的值Bentley Motors转换为两个单独的术语bentleymotors

您可以在条款查询中仅使用bentleymotors进行检查:您将找到您的文档。

然后尝试更改您的第二个请求以使用Bentley Motors匹配查询:您也应该检索您的文档。

如果您要对第二个请求使用条款查询,则必须将公司名称字段的映射设置为 not_analyzed