ElasticSearch选择与大量文档不同?

时间:2017-10-02 15:14:52

标签: elasticsearch

我有一个包含约1亿个文档的索引。有时我想检索所有文档,有时我想按特定字段分组,每个唯一值只选择一个文档。类似的东西:

SELECT * FROM documents GROUP BY my_field;

为了说明,有时我想得到:

|id|my_field|thing  |
|--|--------|-------|
|1 |a       |red    |
|2 |b       |yellow |
|3 |b       |green  |
|4 |c       |brown  |

有时候

|id|my_field|thing  |
|--|--------|-------|
|1 |a       |red    |
|3 |b       |green  |
|4 |c       |brown  |

ElasticSearch文档表明Terms Aggregation符合此用途。但是,有人建议这只适用于汇总术语的小基数,即少量的桶#':

  

有时在单个请求/响应对中处理的唯一术语太多,因此将分析分解为多个请求会很有用

除此之外,Top Hits aggregation还会以不会轻易分页的格式返回数据。

例如,如果我有一百万个不同的术语,我认为它不会与预期的设计完全一致。这是对的吗?

我的另一种方法是在我自己的代码中维护一个索引并标记重复项,但这很容易出错,但会出现并发问题等。

有没有办法实现我想要的ElasticSearch的优势?

2 个答案:

答案 0 :(得分:1)

看起来这不是ElasticSearch索引/聚合的最佳用例。我用另一种方式解决了我的问题 - 通过创建一个单独的类型(或索引)来存储我的数据的重复数据删除视图。我使用唯一对的哈希值作为_timestamp字段,因此ElasticSearch会自动对文档进行重复数据删除。

作为一项额外功能,使用外部<div class="panel-radio-buttons"> <form id="SettingMixRadioButtonsGroup1"> <label class="radio-inline"><input type="radio" name="radio1" value="1" id="BtnEnrollmentsInpatient" ng-model="togglePefsBifsTimeFrame" ng-change='SetDay()'>Daily</label> <label class="radio-inline"><input type="radio" name="radio1" value="2" id="BtnEnrollmentsInpatient2" ng-model="togglePefsBifsTimeFrame" ng-change='SetWeek()' >Weekly</label> <label class="radio-inline"><input type="radio" name="radio1" value="3" id="BtnEnrollmentsInpatient3" ng-model="togglePefsBifsTimeFrame" ng-change='SetMonth()'>Monthly</label> </form> </div> <div class="panel-radio-buttons"> <form id="SettingMixRadioButtonsGroup2"> <label class="radio-inline"><input type="radio" name="radio1" value="1" id="BtnEnrollmentsInpatient4" ng-model="togglePefsBifsTimeFrame" ng-change='SetDay()'>Daily</label> <label class="radio-inline"><input type="radio" name="radio1" value="2" id="BtnEnrollmentsInpatient5" ng-model="togglePefsBifsTimeFrame" ng-change='SetWeek()' ng-checked="togglePefsBifsTimeFrame2" >Weekly</label> <label class="radio-inline"><input type="radio" name="radio1" value="3" id="BtnEnrollmentsInpatient6" ng-model="togglePefsBifsTimeFrame" ng-change='SetMonth()'>Monthly</label> </form> </div> 可以让我选择在重复的情况下存储哪个文档。

答案 1 :(得分:0)

我相信你的评估是正确的,虽然基数为适合这里,你可能遇到不同价值的规模会产生问题。 This type of aggregation是我在ElasticSearch中发现的最接近“GROUP BY”的东西。

话虽如此,我认为有一种方法可以完成

  

为每个唯一值仅选择一个文档。

通过嵌套在“应该”父级中的多个查询。

您的方法会有很大不同,具体取决于您是仅针对聚合计数还是返回值。

我最初的倾向是将您的请求视为嵌套在其中的一组兄弟查询。该方法的问题是基于匹配的大多数字段而不是每个不同查询的第一个文档返回。据我所知,“应该”查询没有任何类型的评分为每个桶返回一个匹配。

以返回文档为目标,我相信您最适合执行multi-search

POST _msearch
{"index":"INDEX"}
{"query":{"match": {"a": "red"}},"size":1}
{"index":"INDEX"}
{"query":{"match": {"b": "yellow"}},"size":1}
{"index":"INDEX"}
{"query":{"match": {"b": "green"}},"size":1}

上面将返回一个匹配每个查询的文档,为您提供一个“结果”对象数组的响应。

原始计数:

POST /INDEX/_search
{
  "size": 0, 
  "aggs": {
    "a_red": {
      "filter": {
        "term": {
          "a": {
            "value": "red"
          }
        }
      }
    },        
    "b_yellow": {
      "filter": {
        "term": {
          "b": {
            "value": "yellow"
          }
        }
      }
    },        
    "b_green": {
      "filter": {
        "term": {
          "b": {
            "value": "green"
          }
        }
      }
    }
  }
}

注意:上面示例的agg存储桶名称(例如:“a_red”)只是为了清晰起见,不是必需的。