240 lines
7.8 KiB
Go
240 lines
7.8 KiB
Go
// Licensed to Elasticsearch B.V. under one or more contributor
|
|
// license agreements. See the NOTICE file distributed with
|
|
// this work for additional information regarding copyright
|
|
// ownership. Elasticsearch B.V. licenses this file to you under
|
|
// the Apache License, Version 2.0 (the "License"); you may
|
|
// not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
package elasticsearch
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// QueryResult contains the result of a query.
|
|
type QueryResult struct {
|
|
Ok bool `json:"ok"`
|
|
Index string `json:"_index"`
|
|
Type string `json:"_type"`
|
|
ID string `json:"_id"`
|
|
Source json.RawMessage `json:"_source"`
|
|
Version int `json:"_version"`
|
|
Exists bool `json:"exists"`
|
|
Found bool `json:"found"` // Only used prior to ES 6. You must also check for Result == "found".
|
|
Created bool `json:"created"` // Only used prior to ES 6. You must also check for Result == "created".
|
|
Result string `json:"result"` // Only used in ES 6+.
|
|
Acknowledged bool `json:"acknowledged"`
|
|
Matches []string `json:"matches"`
|
|
}
|
|
|
|
// SearchResults contains the results of a search.
|
|
type SearchResults struct {
|
|
Took int `json:"took"`
|
|
Shards json.RawMessage `json:"_shards"`
|
|
Hits Hits `json:"hits"`
|
|
Aggs map[string]json.RawMessage `json:"aggregations"`
|
|
}
|
|
|
|
// Hits contains the hits.
|
|
type Hits struct {
|
|
Total int
|
|
Hits []json.RawMessage `json:"hits"`
|
|
}
|
|
|
|
// CountResults contains the count of results.
|
|
type CountResults struct {
|
|
Count int `json:"count"`
|
|
Shards json.RawMessage `json:"_shards"`
|
|
}
|
|
|
|
func withQueryResult(status int, resp []byte, err error) (int, *QueryResult, error) {
|
|
if err != nil {
|
|
return status, nil, errors.Wrapf(err, "Elasticsearch response: %s", resp)
|
|
}
|
|
result, err := readQueryResult(resp)
|
|
return status, result, err
|
|
}
|
|
|
|
func readQueryResult(obj []byte) (*QueryResult, error) {
|
|
var result QueryResult
|
|
if obj == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
err := json.Unmarshal(obj, &result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &result, err
|
|
}
|
|
|
|
func readSearchResult(obj []byte) (*SearchResults, error) {
|
|
var result SearchResults
|
|
if obj == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
err := json.Unmarshal(obj, &result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &result, err
|
|
}
|
|
|
|
func readCountResult(obj []byte) (*CountResults, error) {
|
|
if obj == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
var result CountResults
|
|
err := json.Unmarshal(obj, &result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &result, err
|
|
}
|
|
|
|
// Index adds or updates a typed JSON document in a specified index, making it
|
|
// searchable. In case id is empty, a new id is created over a HTTP POST request.
|
|
// Otherwise, a HTTP PUT request is issued.
|
|
// Implements: http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html
|
|
func (es *Connection) Index(
|
|
index, docType, id string,
|
|
params map[string]string,
|
|
body interface{},
|
|
) (int, *QueryResult, error) {
|
|
method := "PUT"
|
|
if id == "" {
|
|
method = "POST"
|
|
}
|
|
return withQueryResult(es.apiCall(method, index, docType, id, "", params, body))
|
|
}
|
|
|
|
// Ingest pushes a pipeline of updates.
|
|
func (es *Connection) Ingest(
|
|
index, docType, pipeline, id string,
|
|
params map[string]string,
|
|
body interface{},
|
|
) (int, *QueryResult, error) {
|
|
method := "PUT"
|
|
if id == "" {
|
|
method = "POST"
|
|
}
|
|
return withQueryResult(es.apiCall(method, index, docType, id, pipeline, params, body))
|
|
}
|
|
|
|
// Refresh an index. Call this after doing inserts or creating/deleting
|
|
// indexes in unit tests.
|
|
func (es *Connection) Refresh(index string) (int, *QueryResult, error) {
|
|
return withQueryResult(es.apiCall("POST", index, "", "_refresh", "", nil, nil))
|
|
}
|
|
|
|
// CreateIndex creates a new index, optionally with settings and mappings passed in
|
|
// the body.
|
|
// Implements: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html
|
|
//
|
|
func (es *Connection) CreateIndex(index string, body interface{}) (int, *QueryResult, error) {
|
|
return withQueryResult(es.apiCall("PUT", index, "", "", "", nil, body))
|
|
}
|
|
|
|
// IndexExists checks if an index exists.
|
|
// Implements: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html
|
|
//
|
|
func (es *Connection) IndexExists(index string) (int, error) {
|
|
status, _, err := es.apiCall("HEAD", index, "", "", "", nil, nil)
|
|
return status, err
|
|
}
|
|
|
|
// Delete deletes a typed JSON document from a specific index based on its id.
|
|
// Implements: http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html
|
|
func (es *Connection) Delete(index string, docType string, id string, params map[string]string) (int, *QueryResult, error) {
|
|
return withQueryResult(es.apiCall("DELETE", index, docType, id, "", params, nil))
|
|
}
|
|
|
|
// PipelineExists checks if a pipeline with name id already exists.
|
|
// Using: https://www.elastic.co/guide/en/elasticsearch/reference/current/get-pipeline-api.html
|
|
func (es *Connection) PipelineExists(id string) (bool, error) {
|
|
status, _, err := es.apiCall("GET", "_ingest", "pipeline", id, "", nil, nil)
|
|
if status == 404 {
|
|
return false, nil
|
|
}
|
|
return status == 200, err
|
|
}
|
|
|
|
// CreatePipeline create a new ingest pipeline with name id.
|
|
// Implements: https://www.elastic.co/guide/en/elasticsearch/reference/current/put-pipeline-api.html
|
|
func (es *Connection) CreatePipeline(
|
|
id string,
|
|
params map[string]string,
|
|
body interface{},
|
|
) (int, *QueryResult, error) {
|
|
return withQueryResult(es.apiCall("PUT", "_ingest", "pipeline", id, "", params, body))
|
|
}
|
|
|
|
// DeletePipeline deletes an ingest pipeline by id.
|
|
// Implements: https://www.elastic.co/guide/en/elasticsearch/reference/current/delete-pipeline-api.html
|
|
func (es *Connection) DeletePipeline(
|
|
id string,
|
|
params map[string]string,
|
|
) (int, *QueryResult, error) {
|
|
return withQueryResult(es.apiCall("DELETE", "_ingest", "pipeline", id, "", params, nil))
|
|
}
|
|
|
|
// SearchURI executes a search request using a URI by providing request parameters.
|
|
// Implements: http://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
|
|
func (es *Connection) SearchURI(index string, docType string, params map[string]string) (int, *SearchResults, error) {
|
|
return es.SearchURIWithBody(index, docType, params, nil)
|
|
}
|
|
|
|
// SearchURIWithBody executes a search request using a URI by providing request
|
|
// parameters and a request body.
|
|
func (es *Connection) SearchURIWithBody(
|
|
index string,
|
|
docType string,
|
|
params map[string]string,
|
|
body interface{},
|
|
) (int, *SearchResults, error) {
|
|
status, resp, err := es.apiCall("GET", index, docType, "_search", "", params, body)
|
|
if err != nil {
|
|
return status, nil, err
|
|
}
|
|
result, err := readSearchResult(resp)
|
|
return status, result, err
|
|
}
|
|
|
|
// CountSearchURI counts the results for a search request.
|
|
func (es *Connection) CountSearchURI(
|
|
index string, docType string,
|
|
params map[string]string,
|
|
) (int, *CountResults, error) {
|
|
status, resp, err := es.apiCall("GET", index, docType, "_count", "", params, nil)
|
|
if err != nil {
|
|
return status, nil, err
|
|
}
|
|
result, err := readCountResult(resp)
|
|
return status, result, err
|
|
}
|
|
|
|
func (es *Connection) apiCall(
|
|
method, index, docType, id, pipeline string,
|
|
params map[string]string,
|
|
body interface{},
|
|
) (int, []byte, error) {
|
|
path, err := makePath(index, docType, id)
|
|
if err != nil {
|
|
return 0, nil, err
|
|
}
|
|
return es.Request(method, path, pipeline, params, body)
|
|
}
|