使用ElasticSearch计算总占用率

cyvaqqii  于 2023-10-17  发布在  ElasticSearch
关注(0)|答案(2)|浏览(115)

我的要求似乎微不足道:“在所有文档的“单词”字段中检索一个特定单词的总占用数。
索引很简单。我只把主要结构:

@Document(indexName = "documents")
public class Document{
@Field(type = FieldType.Nested, fielddata = true, name = "words")
private List<Word> words;
}

public class Word{
    @Field(type = FieldType.Text, fielddata = true)
    @NotBlank private String data;

    //...other fields
}

我正在使用Elasticseatch API for Java。
我发现的唯一解决方案是重新计算返回的SearchHit列表,并对每个项目的totalHits求和。
但是这个解决方案太昂贵了。

dm7nw8vv

dm7nw8vv1#

您可以启用fielddata来实现您想要的结果。
注意:在内存中加载字段数据可能会占用大量内存。

PUT test_content/_doc/1
{
  "content": "first test"
}

PUT test_content/_doc/2
{
  "content": "second test"
}

GET test_content/_search
{
  "size": 0,
  "aggs": {
    "NAME": {
      "terms": {
        "field": "content",
        "size": 1000000
      }
    }
  }
}

GET test_content/_mapping
PUT test_content/_mapping
{
  "properties": {
    "content": {
      "type": "text",
      "fielddata": true,
      "fields": {
        "keyword": {
          "type": "keyword",
          "ignore_above": 256
        }
      }
    }
  }
}

当您运行此命令时,您将得到以下错误:

非法_参数_异常字段数据在[]中的[]上被禁用。文本字段没有针对需要每个文档字段数据的操作(如聚合和排序)进行优化,因此默认情况下禁用这些操作。请改用关键字字段。或者,在[content]上设置fielddata=true,以便通过不反转倒排索引来加载字段数据。请注意,这可能会占用大量内存。
如果这是一次性或罕见的操作,您可以启用它。

请注意,您在下面看到的结果是包含相关单词的文档计数。例如,有两个单词包含单词“test”。这意味着即使单词“test”在同一文档中出现多次,它也将被计为一次。

qyuhtwio

qyuhtwio2#

我是这样解决的:

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(
                QueryBuilders.wrapperQuery(QueryUtils.toQuery(template.getKeyword(), "words.data"))
        );

        FilterAggregationBuilder filterAgg = AggregationBuilders.filter("filter_aggr", boolQueryBuilder);
        NestedAggregationBuilder nestedAgg = AggregationBuilders.nested("nested_aggr", "words").subAggregation(filterAgg);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(
                QueryBuilders.matchAllQuery()
        );
        searchSourceBuilder.aggregation(nestedAgg);
        searchSourceBuilder.size(0);
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.source(searchSourceBuilder);
        org.elasticsearch.action.search.SearchResponse s = clientConfig.elasticsearchClient().search(searchRequest, RequestOptions.DEFAULT);
        return ((ParsedFilter)((ParsedNested)(s.getAggregations().get("nested_aggr"))).getAggregations().get("filter_aggr")).getDocCount();

相关问题