Skip to content

Commit 93c45de

Browse files
larrycinnabarolivere
authored andcommitted
Add column aliases in cat indices API (#1236)
This commit allows to specify aliases to the cat indices API, in the same way that the `curl` command does when using the `_cat/indices` endpoint.
1 parent 333a71f commit 93c45de

File tree

2 files changed

+212
-2
lines changed

2 files changed

+212
-2
lines changed

cat_indices.go

+158-2
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ package elastic
77
import (
88
"context"
99
"fmt"
10+
"github.com/olivere/elastic/v7/uritemplates"
1011
"net/http"
1112
"net/url"
1213
"strings"
13-
14-
"github.com/olivere/elastic/v7/uritemplates"
1514
)
1615

1716
// CatIndicesService returns the list of indices plus some additional
@@ -189,6 +188,22 @@ func (s *CatIndicesService) buildURL() (string, url.Values, error) {
189188
params.Set("master_timeout", s.masterTimeout)
190189
}
191190
if len(s.columns) > 0 {
191+
// loop through all columns and apply alias if needed
192+
for i, column := range s.columns {
193+
if fullValueRaw, isAliased := catIndicesResponseRowAliasesMap[column]; isAliased {
194+
// alias can be translated to multiple fields,
195+
// so if translated value contains a comma, than replace the first value
196+
// and append the others
197+
if strings.Contains(fullValueRaw, ",") {
198+
fullValues := strings.Split(fullValueRaw, ",")
199+
s.columns[i] = fullValues[0]
200+
s.columns = append(s.columns, fullValues[1:]...)
201+
} else {
202+
s.columns[i] = fullValueRaw
203+
}
204+
}
205+
}
206+
192207
params.Set("h", strings.Join(s.columns, ","))
193208
}
194209
if s.health != "" {
@@ -372,3 +387,144 @@ type CatIndicesResponseRow struct {
372387
MemoryTotal string `json:"memory.total"` // total user memory on primaries & replicas, e.g. "1.5kb"
373388
PriMemoryTotal string `json:"pri.memory.total"` // total user memory on primaries, e.g. "1.5kb"
374389
}
390+
391+
// catIndicesResponseRowAliasesMap holds the global map for columns aliases
392+
// the map is used by CatIndicesService.buildURL
393+
// for backwards compatibility some fields are able to have the same aliases
394+
// that means that one alias can be translated to different columns (from different elastic versions)
395+
// example for understanding: rto -> RefreshTotal, RefreshExternalTotal
396+
var catIndicesResponseRowAliasesMap = map[string]string{
397+
"qce": "query_cache.evictions",
398+
"searchFetchTime": "search.fetch_time",
399+
"memoryTotal": "memory.total",
400+
"requestCacheEvictions": "request_cache.evictions",
401+
"ftt": "flush.total_time",
402+
"iic": "indexing.index_current",
403+
"mtt": "merges.total_time",
404+
"scti": "search.scroll_time",
405+
"searchScrollTime": "search.scroll_time",
406+
"segmentsCount": "segments.count",
407+
"getTotal": "get.total",
408+
"sfti": "search.fetch_time",
409+
"searchScrollCurrent": "search.scroll_current",
410+
"svmm": "segments.version_map_memory",
411+
"warmerTotalTime": "warmer.total_time",
412+
"r": "rep",
413+
"indexingIndexTime": "indexing.index_time",
414+
"refreshTotal": "refresh.total,refresh.external_total",
415+
"scc": "search.scroll_current",
416+
"suggestTime": "suggest.time",
417+
"idc": "indexing.delete_current",
418+
"rti": "refresh.time,refresh.external_time",
419+
"sfto": "search.fetch_total",
420+
"completionSize": "completion.size",
421+
"mt": "merges.total",
422+
"segmentsVersionMapMemory": "segments.version_map_memory",
423+
"rto": "refresh.total,refresh.external_total",
424+
"id": "uuid",
425+
"dd": "docs.deleted",
426+
"docsDeleted": "docs.deleted",
427+
"fielddataMemory": "fielddata.memory_size",
428+
"getTime": "get.time",
429+
"getExistsTime": "get.exists_time",
430+
"mtd": "merges.total_docs",
431+
"rli": "refresh.listeners",
432+
"h": "health",
433+
"cds": "creation.date.string",
434+
"rcmc": "request_cache.miss_count",
435+
"iif": "indexing.index_failed",
436+
"warmerCurrent": "warmer.current",
437+
"gti": "get.time",
438+
"indexingIndexFailed": "indexing.index_failed",
439+
"mts": "merges.total_size",
440+
"sqti": "search.query_time",
441+
"segmentsIndexWriterMemory": "segments.index_writer_memory",
442+
"iiti": "indexing.index_time",
443+
"iito": "indexing.index_total",
444+
"cd": "creation.date",
445+
"gc": "get.current",
446+
"searchFetchTotal": "search.fetch_total",
447+
"sqc": "search.query_current",
448+
"segmentsMemory": "segments.memory",
449+
"dc": "docs.count",
450+
"qcm": "query_cache.memory_size",
451+
"queryCacheMemory": "query_cache.memory_size",
452+
"mergesTotalDocs": "merges.total_docs",
453+
"searchOpenContexts": "search.open_contexts",
454+
"shards.primary": "pri",
455+
"cs": "completion.size",
456+
"mergesTotalTIme": "merges.total_time",
457+
"wtt": "warmer.total_time",
458+
"mergesCurrentSize": "merges.current_size",
459+
"mergesTotal": "merges.total",
460+
"refreshTime": "refresh.time,refresh.external_time",
461+
"wc": "warmer.current",
462+
"p": "pri",
463+
"idti": "indexing.delete_time",
464+
"searchQueryCurrent": "search.query_current",
465+
"warmerTotal": "warmer.total",
466+
"suggestTotal": "suggest.total",
467+
"tm": "memory.total",
468+
"ss": "store.size",
469+
"ft": "flush.total",
470+
"getExistsTotal": "get.exists_total",
471+
"scto": "search.scroll_total",
472+
"s": "status",
473+
"queryCacheEvictions": "query_cache.evictions",
474+
"rce": "request_cache.evictions",
475+
"geto": "get.exists_total",
476+
"refreshListeners": "refresh.listeners",
477+
"suto": "suggest.total",
478+
"storeSize": "store.size",
479+
"gmti": "get.missing_time",
480+
"indexingIdexCurrent": "indexing.index_current",
481+
"searchFetchCurrent": "search.fetch_current",
482+
"idx": "index",
483+
"fm": "fielddata.memory_size",
484+
"geti": "get.exists_time",
485+
"indexingDeleteCurrent": "indexing.delete_current",
486+
"mergesCurrentDocs": "merges.current_docs",
487+
"sth": "search.throttled",
488+
"flushTotal": "flush.total",
489+
"sfc": "search.fetch_current",
490+
"wto": "warmer.total",
491+
"suti": "suggest.time",
492+
"shardsReplica": "rep",
493+
"mergesCurrent": "merges.current",
494+
"mcs": "merges.current_size",
495+
"so": "search.open_contexts",
496+
"i": "index",
497+
"siwm": "segments.index_writer_memory",
498+
"sfbm": "segments.fixed_bitset_memory",
499+
"fe": "fielddata.evictions",
500+
"requestCacheMissCount": "request_cache.miss_count",
501+
"idto": "indexing.delete_total",
502+
"mergesTotalSize": "merges.total_size",
503+
"suc": "suggest.current",
504+
"suggestCurrent": "suggest.current",
505+
"flushTotalTime": "flush.total_time",
506+
"getMissingTotal": "get.missing_total",
507+
"sqto": "search.query_total",
508+
"searchScrollTotal": "search.scroll_total",
509+
"fixedBitsetMemory": "segments.fixed_bitset_memory",
510+
"getMissingTime": "get.missing_time",
511+
"indexingDeleteTotal": "indexing.delete_total",
512+
"mcd": "merges.current_docs",
513+
"docsCount": "docs.count",
514+
"gto": "get.total",
515+
"mc": "merges.current",
516+
"fielddataEvictions": "fielddata.evictions",
517+
"rcm": "request_cache.memory_size",
518+
"requestCacheHitCount": "request_cache.hit_count",
519+
"gmto": "get.missing_total",
520+
"searchQueryTime": "search.query_time",
521+
"shards.replica": "rep",
522+
"requestCacheMemory": "request_cache.memory_size",
523+
"rchc": "request_cache.hit_count",
524+
"getCurrent": "get.current",
525+
"indexingIndexTotal": "indexing.index_total",
526+
"sc": "segments.count,segments.memory",
527+
"shardsPrimary": "pri",
528+
"indexingDeleteTime": "indexing.delete_time",
529+
"searchQueryTotal": "search.query_total",
530+
}

cat_indices_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,57 @@ func TestCatIndices(t *testing.T) {
2626
t.Fatalf("Index[0]: want != %q, have %q", "", have)
2727
}
2828
}
29+
30+
// TestCatIndicesResponseRowAliasesMap tests if catIndicesResponseRowAliasesMap is declared
31+
func TestCatIndicesResponseRowAliasesMap(t *testing.T) {
32+
if catIndicesResponseRowAliasesMap == nil {
33+
t.Fatal("want catIndicesResponseRowAliasesMap to be not nil")
34+
}
35+
36+
if len(catIndicesResponseRowAliasesMap) == 0 {
37+
t.Fatal("want catIndicesResponseRowAliasesMap to be not empty")
38+
}
39+
}
40+
41+
// TestCatIndicesWithAliases makes a simple test (if ?h=h will be the same as ?h=health)
42+
func TestCatIndicesWithAliases(t *testing.T) {
43+
client := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, "", 0)))
44+
ctx := context.Background()
45+
res, err := client.CatIndices().Columns("h").Do(ctx)
46+
if err != nil {
47+
t.Fatal(err)
48+
}
49+
if res == nil {
50+
t.Fatal("want response, have nil")
51+
}
52+
if len(res) == 0 {
53+
t.Fatalf("want response, have: %v", res)
54+
}
55+
if have := res[0].Health; have == "" {
56+
t.Fatalf("Index[0]: want != %q, have %q", "", have)
57+
}
58+
}
59+
60+
// TestCatIndicesWithAliases makes a test with a double-alias
61+
// asking `?h=rti` will fill one of the refresh.external_time/refresh.time fields (depending on elasticsearch version)
62+
func TestCatIndicesWithAliases_Double(t *testing.T) {
63+
client := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, "", 0)))
64+
ctx := context.Background()
65+
res, err := client.CatIndices().Columns("rti").Do(ctx)
66+
if err != nil {
67+
t.Fatal(err)
68+
}
69+
if res == nil {
70+
t.Fatal("want response, have nil")
71+
}
72+
if len(res) == 0 {
73+
t.Fatalf("want response, have: %v", res)
74+
}
75+
76+
refreshTime := res[0].RefreshTime
77+
refreshExternalTime := res[0].RefreshExternalTime
78+
79+
if refreshTime == "" && refreshExternalTime == "" {
80+
t.Fatalf("Index[0]: want one of [refreshTime or refreshExternalTime] be not empty")
81+
}
82+
}

0 commit comments

Comments
 (0)