languages
レコードからすべての値を取得して、それらを一意にする方法を教えてください。
記録
PUT items/1
{ "language" : 10 }
PUT items/2
{ "language" : 11 }
PUT items/3
{ "language" : 10 }
クエリ
GET items/_search
{ ... }
# => Expected Response
[10, 11]
どんな助けでも素晴らしいでしょう。
languages
レコードからすべての値を取得して、それらを一意にする方法を教えてください。
記録
PUT items/1
{ "language" : 10 }
PUT items/2
{ "language" : 11 }
PUT items/3
{ "language" : 10 }
クエリ
GET items/_search
{ ... }
# => Expected Response
[10, 11]
どんな助けでも素晴らしいでしょう。
回答:
集計という用語を使用できます。
{
"size": 0,
"aggs" : {
"langs" : {
"terms" : { "field" : "language", "size" : 500 }
}
}}
検索は次のようなものを返します:
{
"took" : 16,
"timed_out" : false,
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"hits" : {
"total" : 1000000,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"langs" : {
"buckets" : [ {
"key" : "10",
"doc_count" : 244812
}, {
"key" : "11",
"doc_count" : 136794
}, {
"key" : "12",
"doc_count" : 32312
} ]
}
}
}
size
集計内のパラメータは、集計結果に含める用語の最大数を指定します。すべての結果が必要な場合は、これをデータ内の一意の用語の数よりも大きい値に設定します。
"fields" : ["language"]
同じ結果をもたらします。回答を拡張して、集計フレームワークが言語値のみを返すことができるかどうかを確認できますか?#=> [10, 11, 10]
language
場合は、size=0
およびを追加してshard_size=0
、すべての値を確実に取得できるようにしてください。elasticsearch.org/guide/en/elasticsearch/reference/current/…を
Elasticsearch 1.1+には、一意のカウントを提供するCardinality Aggregationがあります。
これは実際には近似値であり、精度が高いカーディナリティデータセットでは低下する可能性がありますが、テストでは一般にかなり正確です。
precision_threshold
パラメータを使用して精度を調整することもできます。トレードオフ、またはコースは、メモリ使用量です。
docsからのこのグラフは、高いほどprecision_threshold
、はるかに正確な結果につながることを示しています。
私自身もこのような解決策を探しています。用語集で参照が見つかりました。
したがって、それによると、以下は適切な解決策です。
{
"aggs" : {
"langs" : {
"terms" : { "field" : "language",
"size" : 500 }
}
}}
しかし、次のエラーが発生した場合:
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [fastest_method] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
}
]}
その場合、次のようにリクエストに「KEYWORD」を追加する必要があります。
{
"aggs" : {
"langs" : {
"terms" : { "field" : "language.keyword",
"size" : 500 }
}
}}
近似値やマジックナンバー(size: 500
)を設定せずにすべての一意の値を取得する場合は、COMPOSITE AGGREGATION(ES 6.5+)を使用します。
公式ドキュメントから:
「ネストされた用語の集計ですべての用語または用語のすべての組み合わせを取得する場合は、COMPOSITE AGGREGATIONを使用する必要があります。これにより、用語集計のフィールドのカーディナリティよりも大きいサイズを設定するのではなく、可能なすべての用語にページ番号を付けることができます。用語の集約は、上位の用語を返すことを意図しており、ページ分割を許可していません。」
JavaScriptでの実装例:
const ITEMS_PER_PAGE = 1000;
const body = {
"size": 0, // Returning only aggregation results: https://www.elastic.co/guide/en/elasticsearch/reference/current/returning-only-agg-results.html
"aggs" : {
"langs": {
"composite" : {
"size": ITEMS_PER_PAGE,
"sources" : [
{ "language": { "terms" : { "field": "language" } } }
]
}
}
}
};
const uniqueLanguages = [];
while (true) {
const result = await es.search(body);
const currentUniqueLangs = result.aggregations.langs.buckets.map(bucket => bucket.key);
uniqueLanguages.push(...currentUniqueLangs);
const after = result.aggregations.langs.after_key;
if (after) {
// continue paginating unique items
body.aggs.langs.composite.after = after;
} else {
break;
}
}
console.log(uniqueLanguages);
fields: [languages]
与えられたフィールドの値のみを与えますが、それらを一意にすることはおそらくコードで行う方が簡単です。あなたのためにそれを行うことができる便利な集約があるかもしれませんが。