如何在ES中获得不同的afeild值?

时间:2018-01-29 01:20:00

标签: elasticsearch

我正在尝试计算ES中字段的不同值。例如,如果我有一个包含以下文档的索引:

$post = Post::find($id);
$post->load('comments.user');
$comments = $post->comments;

我希望得到这样的输出:

{
    "NAME": "XYZ",
    "TITLE": "ABC"
}

{
    "NAME": "RTY",
    "TITLE": "BNM"
}

如何在" title"中获取不同的值?这种格式的字段。我尝试过使用聚合但输出非常好。请帮忙。

1 个答案:

答案 0 :(得分:1)

测试数据:

PUT http://localhost:9200/stackoverflow/os/1
{
    "NAME": "XYZ",
    "TITLE": "LINUX OS"
}

PUT http://localhost:9200/stackoverflow/os/1
{
    "NAME": "XYZ",
    "TITLE": "WINDOWS SERVER"
}

首次查询尝试:

注意我在这里使用POST而不是GET,因为大多数REST客户端不支持GET的有效负载。

POST http://localhost:9200/stackoverflow/_search
{
   "size":0,
   "aggs":{
      "uniq_soft_tags":{
         "terms":{
            "field":"TITLE"
         }
      }
   }
}

如果您没有为数据提供映射并运行上述内容,那么很可能您最终会遇到以下错误。

Fielddata is disabled on text fields by default. Set fielddata=true on [TITLE] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory

详细了解here

添加映射以启用Fielddata:

PUT http://localhost:9200/stackoverflow/_mapping/os/
{
  "properties": {
    "TITLE": { 
      "type":     "text",
      "fielddata": true
    }
  }
}

第二次查询尝试:

POST http://localhost:9200/stackoverflow/_search
{
   "size":0,
   "aggs":{
      "uniq_soft_tags":{
         "terms":{
            "field":"TITLE"
         }
      }
   }
}

<强>结果:

{
    "took": 10,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 2,
        "max_score": 0,
        "hits": []
    },
    "aggregations": {
        "uniq_soft_tags": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": "linux",
                    "doc_count": 1
                },
                {
                    "key": "os",
                    "doc_count": 1
                },
                {
                    "key": "server",
                    "doc_count": 1
                },
                {
                    "key": "windows",
                    "doc_count": 1
                }
            ]
        }
    }
}

请注意,此处的doc_counts是近似值。

请务必阅读文档中的以下部分。 https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html#before-enabling-fielddata

这解释了你如何得到这种诽谤行为。

  

启用fielddata之前

     

在启用fielddata之前,请考虑使用文本字段的原因   用于聚合,排序或脚本。它通常不会   这样做的意义。

     

在索引之前分析文本字段,以便像纽约这样的值   可以通过搜索新的或约克找到。术语聚合   当你这个时,这个字段会返回一个新桶和一个约克桶   可能想要一个名为纽约的桶。

<强>更新

要防止拆分行为,您必须提供如下映射。请注意,使用此方法,您不需要先将Mappingdata设置为true的映射。

PUT http://localhost:9200/stackoverflow/_mapping/os/
{
  "properties": {
    "TITLE": { 
      "type":     "text",
      "fields": {
        "keyword": { 
          "type": "keyword"
        }
      }
    }
  }
}

现在我们可以用, 用于搜索的 TITLE 字段。 用于聚合,排序或脚本的 TITLE.keyword 字段。

第三次查询尝试:

POST http://localhost:9200/stackoverflow/_search
{
   "size":0,
   "aggs":{
      "uniq_soft_tags":{
         "terms":{
            "field":"TITLE.keyword"
         }
      }
   }
}

<强>结果:

{
    "took": 59,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 2,
        "max_score": 0,
        "hits": []
    },
    "aggregations": {
        "uniq_soft_tags": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": "LINUX OS",
                    "doc_count": 1
                },
                {
                    "key": "WINDOWS SERVER",
                    "doc_count": 1
                }
            ]
        }
    }
}