-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit adds the Indices Segments API.
- Loading branch information
Showing
4 changed files
with
317 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
// Copyright 2012-present Oliver Eilhard. All rights reserved. | ||
// Use of this source code is governed by a MIT-license. | ||
// See http://olivere.mit-license.org/license.txt for details. | ||
|
||
package elastic | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/url" | ||
"strings" | ||
|
||
"gopkg.in/olivere/elastic.v5/uritemplates" | ||
) | ||
|
||
// IndicesSegmentsService provides low level segments information that a | ||
// Lucene index (shard level) is built with. Allows to be used to provide | ||
// more information on the state of a shard and an index, possibly | ||
// optimization information, data "wasted" on deletes, and so on. | ||
// | ||
// Find further documentation at | ||
// https://www.elastic.co/guide/en/elasticsearch/reference/5.6/indices-segments.html. | ||
type IndicesSegmentsService struct { | ||
client *Client | ||
pretty bool | ||
index []string | ||
allowNoIndices *bool | ||
expandWildcards string | ||
ignoreUnavailable *bool | ||
human *bool | ||
operationThreading interface{} | ||
verbose *bool | ||
} | ||
|
||
// NewIndicesSegmentsService creates a new IndicesSegmentsService. | ||
func NewIndicesSegmentsService(client *Client) *IndicesSegmentsService { | ||
return &IndicesSegmentsService{ | ||
client: client, | ||
} | ||
} | ||
|
||
// Index is a comma-separated list of index names; use `_all` or empty string | ||
// to perform the operation on all indices. | ||
func (s *IndicesSegmentsService) Index(indices ...string) *IndicesSegmentsService { | ||
s.index = append(s.index, indices...) | ||
return s | ||
} | ||
|
||
// AllowNoIndices indicates whether to ignore if a wildcard indices expression | ||
// resolves into no concrete indices. (This includes `_all` string or when | ||
// no indices have been specified). | ||
func (s *IndicesSegmentsService) AllowNoIndices(allowNoIndices bool) *IndicesSegmentsService { | ||
s.allowNoIndices = &allowNoIndices | ||
return s | ||
} | ||
|
||
// ExpandWildcards indicates whether to expand wildcard expression to concrete indices | ||
// that are open, closed or both. | ||
func (s *IndicesSegmentsService) ExpandWildcards(expandWildcards string) *IndicesSegmentsService { | ||
s.expandWildcards = expandWildcards | ||
return s | ||
} | ||
|
||
// IgnoreUnavailable indicates whether specified concrete indices should be | ||
// ignored when unavailable (missing or closed). | ||
func (s *IndicesSegmentsService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesSegmentsService { | ||
s.ignoreUnavailable = &ignoreUnavailable | ||
return s | ||
} | ||
|
||
// Human, when set to true, returns time and byte-values in human-readable format. | ||
func (s *IndicesSegmentsService) Human(human bool) *IndicesSegmentsService { | ||
s.human = &human | ||
return s | ||
} | ||
|
||
// OperationThreading is undocumented in Elasticsearch as of now. | ||
func (s *IndicesSegmentsService) OperationThreading(operationThreading interface{}) *IndicesSegmentsService { | ||
s.operationThreading = operationThreading | ||
return s | ||
} | ||
|
||
// Verbose, when set to true, includes detailed memory usage by Lucene. | ||
func (s *IndicesSegmentsService) Verbose(verbose bool) *IndicesSegmentsService { | ||
s.verbose = &verbose | ||
return s | ||
} | ||
|
||
// Pretty indicates that the JSON response be indented and human readable. | ||
func (s *IndicesSegmentsService) Pretty(pretty bool) *IndicesSegmentsService { | ||
s.pretty = pretty | ||
return s | ||
} | ||
|
||
// buildURL builds the URL for the operation. | ||
func (s *IndicesSegmentsService) buildURL() (string, url.Values, error) { | ||
var err error | ||
var path string | ||
|
||
if len(s.index) > 0 { | ||
path, err = uritemplates.Expand("/{index}/_segments", map[string]string{ | ||
"index": strings.Join(s.index, ","), | ||
}) | ||
} else { | ||
path = "/_segments" | ||
} | ||
if err != nil { | ||
return "", url.Values{}, err | ||
} | ||
|
||
// Add query string parameters | ||
params := url.Values{} | ||
if s.pretty { | ||
params.Set("pretty", "true") | ||
} | ||
if s.allowNoIndices != nil { | ||
params.Set("allow_no_indices", fmt.Sprintf("%v", *s.allowNoIndices)) | ||
} | ||
if s.expandWildcards != "" { | ||
params.Set("expand_wildcards", s.expandWildcards) | ||
} | ||
if s.ignoreUnavailable != nil { | ||
params.Set("ignore_unavailable", fmt.Sprintf("%v", *s.ignoreUnavailable)) | ||
} | ||
if s.human != nil { | ||
params.Set("human", fmt.Sprintf("%v", *s.human)) | ||
} | ||
if s.operationThreading != nil { | ||
params.Set("operation_threading", fmt.Sprintf("%v", s.operationThreading)) | ||
} | ||
if s.verbose != nil { | ||
params.Set("verbose", fmt.Sprintf("%v", *s.verbose)) | ||
} | ||
return path, params, nil | ||
} | ||
|
||
// Validate checks if the operation is valid. | ||
func (s *IndicesSegmentsService) Validate() error { | ||
return nil | ||
} | ||
|
||
// Do executes the operation. | ||
func (s *IndicesSegmentsService) Do(ctx context.Context) (*IndicesSegmentsResponse, error) { | ||
// Check pre-conditions | ||
if err := s.Validate(); err != nil { | ||
return nil, err | ||
} | ||
|
||
// Get URL for request | ||
path, params, err := s.buildURL() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Get HTTP response | ||
res, err := s.client.PerformRequestWithOptions(ctx, PerformRequestOptions{ | ||
Method: "GET", | ||
Path: path, | ||
Params: params, | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Return operation response | ||
ret := new(IndicesSegmentsResponse) | ||
if err := json.Unmarshal(res.Body, ret); err != nil { | ||
return nil, err | ||
} | ||
return ret, nil | ||
} | ||
|
||
// IndicesSegmentsResponse is the response of IndicesSegmentsService.Do. | ||
type IndicesSegmentsResponse struct { | ||
// Shards provides information returned from shards. | ||
Shards shardsInfo `json:"_shards"` | ||
|
||
// Indices provides a map into the stats of an index. | ||
// The key of the map is the index name. | ||
Indices map[string]*IndexSegments `json:"indices,omitempty"` | ||
} | ||
|
||
type IndexSegments struct { | ||
// Shards provides a map into the shard related information of an index. | ||
// The key of the map is the number of a specific shard. | ||
Shards map[string][]*IndexSegmentsShards `json:"shards,omitempty"` | ||
} | ||
|
||
type IndexSegmentsShards struct { | ||
Routing *IndexSegmentsRouting `json:"routing,omitempty"` | ||
NumCommittedSegments int64 `json:"num_committed_segments,omitempty"` | ||
NumSearchSegments int64 `json:"num_search_segments"` | ||
|
||
// Segments provides a map into the segment related information of a shard. | ||
// The key of the map is the specific lucene segment id. | ||
Segments map[string]*IndexSegmentsDetails `json:"segments,omitempty"` | ||
} | ||
|
||
type IndexSegmentsRouting struct { | ||
State string `json:"state,omitempty"` | ||
Primary bool `json:"primary,omitempty"` | ||
Node string `json:"node,omitempty"` | ||
RelocatingNode string `json:"relocating_node,omitempty"` | ||
} | ||
|
||
type IndexSegmentsDetails struct { | ||
Generation int64 `json:"generation,omitempty"` | ||
NumDocs int64 `json:"num_docs,omitempty"` | ||
DeletedDocs int64 `json:"deleted_docs,omitempty"` | ||
Size string `json:"size,omitempty"` | ||
SizeInBytes int64 `json:"size_in_bytes,omitempty"` | ||
Memory string `json:"memory,omitempty"` | ||
MemoryInBytes int64 `json:"memory_in_bytes,omitempty"` | ||
Committed bool `json:"committed,omitempty"` | ||
Search bool `json:"search,omitempty"` | ||
Version string `json:"version,omitempty"` | ||
Compound bool `json:"compound,omitempty"` | ||
MergeId string `json:"merge_id,omitempty"` | ||
RAMTree []*IndexSegmentsRamTree `json:"ram_tree,omitempty"` | ||
} | ||
|
||
type IndexSegmentsRamTree struct { | ||
Description string `json:"description,omitempty"` | ||
Size string `json:"size,omitempty"` | ||
SizeInBytes int64 `json:"size_in_bytes,omitempty"` | ||
Children []*IndexSegmentsRamTree `json:"children,omitempty"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright 2012-present Oliver Eilhard. All rights reserved. | ||
// Use of this source code is governed by a MIT-license. | ||
// See http://olivere.mit-license.org/license.txt for details. | ||
|
||
package elastic | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
) | ||
|
||
func TestIndicesSegments(t *testing.T) { | ||
client := setupTestClientAndCreateIndex(t) | ||
|
||
tests := []struct { | ||
Indices []string | ||
Expected string | ||
}{ | ||
{ | ||
[]string{}, | ||
"/_segments", | ||
}, | ||
{ | ||
[]string{"index1"}, | ||
"/index1/_segments", | ||
}, | ||
{ | ||
[]string{"index1", "index2"}, | ||
"/index1%2Cindex2/_segments", | ||
}, | ||
} | ||
|
||
for i, test := range tests { | ||
path, _, err := client.IndexSegments().Index(test.Indices...).buildURL() | ||
if err != nil { | ||
t.Errorf("case #%d: %v", i+1, err) | ||
} | ||
if path != test.Expected { | ||
t.Errorf("case #%d: expected %q; got: %q", i+1, test.Expected, path) | ||
} | ||
} | ||
} | ||
|
||
func TestIndexSegments(t *testing.T) { | ||
client := setupTestClientAndCreateIndexAndAddDocs(t) | ||
//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, "", 0))) | ||
|
||
segments, err := client.IndexSegments(testIndexName).Pretty(true).Human(true).Do(context.TODO()) | ||
if err != nil { | ||
t.Fatalf("expected no error; got: %v", err) | ||
} | ||
if segments == nil { | ||
t.Fatalf("expected response; got: %v", segments) | ||
} | ||
indices, found := segments.Indices[testIndexName] | ||
if !found { | ||
t.Fatalf("expected index information about index %v; got: %v", testIndexName, found) | ||
} | ||
shards, found := indices.Shards["0"] | ||
if !found { | ||
t.Fatalf("expected shard information about index %v", testIndexName) | ||
} | ||
if shards == nil { | ||
t.Fatalf("expected shard information to be != nil for index %v", testIndexName) | ||
} | ||
shard := shards[0] | ||
if shard == nil { | ||
t.Fatalf("expected shard information to be != nil for shard 0 in index %v", testIndexName) | ||
} | ||
if shard.Routing == nil { | ||
t.Fatalf("expected shard routing information to be != nil for index %v", testIndexName) | ||
} | ||
segmentDetail, found := shard.Segments["_0"] | ||
if !found { | ||
t.Fatalf("expected segment detail to be != nil for index %v", testIndexName) | ||
} | ||
if segmentDetail == nil { | ||
t.Fatalf("expected segment detail to be != nil for index %v", testIndexName) | ||
} | ||
if segmentDetail.NumDocs == 0 { | ||
t.Fatal("expected segment to contain >= 1 docs") | ||
} | ||
} |