根据弹性搜索文档,https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-termvectors.html,术语向量只能应用于文档。有什么方法可以在索引级别应用它。
我的用例是在应用英语停用词过滤器后,计算添加到索引的所有文档中存在的字段(类型:字符串,基本上是一个句子)中的所有 uni、bi 和 trigram 的频率。
谢谢。
使用术语向量存储分片中所有文档的一些统计数据(为什么不索引?...继续阅读)。
要使其发挥作用,您必须为要分析的字段启用 term_vectors。最好的方法是在设置映射时将 term_vectors 添加到字段定义中,因为计算是在索引时完成的,这可以加快术语向量检索的速度。
然后,在检索术语向量时,只需添加“term_statistics”参数,ttf 就会包含在输出中。看这个例子:
GET /twitter/_doc/1/_termvectors { "fields" : ["text"], "offsets" :true,“有效负载”:true,“位置”:true,“term_statistics” :正确,“field_statistics”:正确}
但是,请注意,如果索引使用多个分片,则 term_vectors 和依赖于 term_vectors 的“更像这样”查询并不准确。 说不是这样的!
术语和字段统计不准确。删除的文档是 没有考虑到。该信息仅针对 请求的文档所在的分片。术语和字段统计 因此,仅作为相对测量有用,而绝对测量 数字在这种情况下没有任何意义。
如果您想要准确的统计数据,则必须将索引设置为单个分片,这违背了使用弹性搜索的目的,因为您无法对单个分片进行集群。 另一个 Stackoverflow 提交者陷入了这个陷阱。如果有人知道解决方案,请发帖。
您可以通过
doc
参数访问术语。但是我找不到访问术语参数(位置和偏移量)的方法。所以唯一的方法就是编写脚本
我使用了
scripted_metric
聚合
使用多字段和
ngrams
标记过滤器进行映射
PUT /ngram_frequencies
{
"mappings": {
"properties": {
"text": {
"type": "text",
"fields": {
"ngrams": {
"type": "text",
"analyzer": "standard_lowercase_ngram_analyzer",
"fielddata": true
}
}
}
}
},
"settings": {
"max_ngram_diff": 3,
"analysis": {
"analyzer": {
"standard_lowercase_ngram_analyzer": {
"tokenizer": "standard",
"filter": [
"lowercase",
"ngram_filter"
]
}
},
"filter": {
"ngram_filter": {
"type": "ngram",
"min_gram": 1,
"max_gram": 3
}
}
}
}
}
文件
PUT /ngram_frequencies/_bulk
{"create":{"_id":1}}
{"text": "abc ab bc"}
{"create":{"_id":2}}
{"text": "a bcd"}
聚合查询
GET /ngram_frequencies/_search?filter_path=aggregations
{
"aggs": {
"per_term_count": {
"scripted_metric": {
"init_script": "state.map = new HashMap()",
"map_script": """
int countOccurrences(String string, String substring) {
int occurrenceCount = 0;
int limit = 0;
int position;
do {
position = string.indexOf(substring, limit);
if (position != -1) {
occurrenceCount++;
limit = position + 1;
}
} while (position != -1);
return occurrenceCount;
}
List terms = doc[params.analyzed_field_with_fielddata];
for (term in terms) {
String text = params['_source']['text'];
int occurrenceCount = countOccurrences(text, term);
state.map[term] = state.map.getOrDefault(term, 0) + occurrenceCount;
}
""",
"combine_script": "return state.map",
"reduce_script": """
Map totalTerms = new HashMap();
for (map in states) {
map.forEach((k,v) -> totalTerms[k] = totalTerms.getOrDefault(k, 0) + v);
}
return totalTerms;
""",
"params": {
"analyzed_field_with_fielddata": "text.ngrams"
}
}
}
}
}
回应
{
"aggregations" : {
"per_term_count" : {
"value" : {
"a" : 3,
"ab" : 2,
"bc" : 3,
"cd" : 1,
"b" : 4,
"bcd" : 1,
"abc" : 1,
"c" : 3,
"d" : 1
}
}
}
}