Elasticsearch通过“部分术语”而不是“整个术语”进行聚合

时间:2014-12-03 17:45:01

标签: database elasticsearch aggregation

我目前正试图在弹性搜索中做一些奇特的事情......它几乎可以工作。

使用案例:我必须将某个字段的结果数量限制为(x)结果。

示例:在一组餐厅中,我只想为每个餐馆名称返回两个位置。如果我搜索墨西哥食物,那么我应该得到(x)Taco Bell命中,(x)Del Taco Hits和(x)El Torito Hits。

问题:我的聚合目前仅匹配该术语的部分内容。

For Instance:如果我尝试匹配company_name,它会为 taco 创建一个存储桶,为 bell 创建另一个存储桶因此,Taco Bell可能会出现在2个桶中,从而导致该公司获得(x) * 2个结果。

我发现很难相信这是理想的行为。有没有办法按整个搜索词聚合?

这是我当前的聚合JSON:

"aggs": {
    "by_company": {
      "terms": {
        "field": "company_name"
      },
      "aggs": {
        "first_hit": {
          "top_hits": {"size":1, "from": 0}
        }
      }
    }
}

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

是。如果您的“company_name”只是标准分析器的常规字符串,或者您使用的“company_name”分析器正在分割名称,那么这就是您的答案。 ES存储“术语”,而不是单词或整个文本,除非您告诉它。

假设您对该字段的当前分析器完全按照上面描述的那样进行,那么您需要另一个 - 让我们称之为“原始” - 应该镜像您的company_name字段的字段,但它应该按原样存储公司名称。

这就是我的意思:

{
  "mappings": {
    "test": {
      "properties": {
        ...,
        "company_name": {
          "type": "multi_field",
          "fields": {
            "company_name": {
              "type": "string" #and whatever you currently have in your mapping for `company_name`
            },
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        }
      }
    }
  }
}

在你的查询中,你会这样做:

"aggs": {
    "by_company": {
      "terms": {
        "field": "company_name.raw"
      },
      "aggs": {
        "first_hit": {
          "top_hits": {"size":1, "from": 0}
        }
      }
    }
}