Code Monkey home page Code Monkey logo

go-elasticsearch's Introduction

go-elasticsearch

The official Go client for Elasticsearch.

Download the latest version of Elasticsearch or sign-up for a free trial of Elastic Cloud.

GoDoc Go Report Card codecov.io Build Unit Integration API

Compatibility

Go

Starting from version 8.12.0, this library follow the Go language policy. Each major Go release is supported until there are two newer major releases. For example, Go 1.5 was supported until the Go 1.7 release, and Go 1.6 was supported until the Go 1.8 release.

Elasticsearch

Language clients are forward compatible; meaning that clients support communicating with greater or equal minor versions of Elasticsearch. Elasticsearch language clients are only backwards compatible with default distributions and without guarantees made.

When using Go modules, include the version in the import path, and specify either an explicit version or a branch:

require github.com/elastic/go-elasticsearch/v8 v8.0.0
require github.com/elastic/go-elasticsearch/v7 7.17

It's possible to use multiple versions of the client in a single project:

// go.mod
github.com/elastic/go-elasticsearch/v7 v7.17.0
github.com/elastic/go-elasticsearch/v8 v8.0.0

// main.go
import (
  elasticsearch7 "github.com/elastic/go-elasticsearch/v7"
  elasticsearch8 "github.com/elastic/go-elasticsearch/v8"
)
// ...
es7, _ := elasticsearch7.NewDefaultClient()
es8, _ := elasticsearch8.NewDefaultClient()

The main branch of the client is compatible with the current master branch of Elasticsearch.

Installation

Refer to the Installation section of the getting started documentation.

Connecting

Refer to the Connecting section of the getting started documentation.

Operations

Helpers

The esutil package provides convenience helpers for working with the client. At the moment, it provides the esutil.JSONReader() and the esutil.BulkIndexer helpers.

Examples

The _examples folder contains a number of recipes and comprehensive examples to get you started with the client, including configuration and customization of the client, using a custom certificate authority (CA) for security (TLS), mocking the transport for unit tests, embedding the client in a custom type, building queries, performing requests individually and in bulk, and parsing the responses.

License

This software is licensed under the Apache 2 license. See NOTICE.

go-elasticsearch's People

Contributors

anaethelion avatar axw avatar benjyiw avatar chzhuo avatar dependabot[bot] avatar haraldnordgren avatar heyanfu avatar johntitor avatar karmi avatar kiivihal avatar kotaroooo0 avatar kusumoto avatar lnnt avatar lpflpf avatar manuelbcd avatar mefuller avatar mehran-prs avatar mpdreamz avatar niuguy avatar philkra avatar ppf2 avatar pzl avatar rockdaboot avatar sethmlarson avatar swallez avatar szabosteve avatar tblyler avatar tty2 avatar xd-deng avatar xeviknal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-elasticsearch's Issues

Invalid time duration formatting

I was trying to do a scroll query and hit an issue caused by the formatting of time durations that are passed to Elasticsearch. You can see and example in:

https://play.golang.org/p/fKd7ErkUTJB

I tracked down the line in the generator but I wasn't exactly sure how to regenerate the source. (I think this would be a good topic for the readme or maybe a contributing doc.)

The scroll time was being formatted based on the Go time.Duration format. So for one minute it would use 16666h40m0s. Elasticsearch supports nanoseconds as a time unit so it can pass the Go time.Duration value through without any conversion just by appending "nanos".

diff --git a/internal/cmd/generate/commands/gensource/generator.go b/internal/cmd/generate/commands/gensource/generator.go
index cf05218..50b7936 100755
--- a/internal/cmd/generate/commands/gensource/generator.go
+++ b/internal/cmd/generate/commands/gensource/generator.go
@@ -625,7 +625,7 @@ func (r ` + g.Endpoint.MethodWithNamespace() + `Request) Do(ctx context.Context,
                                fieldValue = `strings.Join(r.` + fieldName + `, ",")`
                        case "time.Duration":
                                fieldCondition = `r.` + fieldName + ` != 0`
-                               fieldValue = `time.Duration(r.` + fieldName + ` * time.Millisecond).String()`
+                               fieldValue = `strconv.FormatInt(int64(r.` + fieldName +`), 10) + "nanos"`
                        default: // interface{}
                                fieldCondition = `r.` + fieldName + ` != nil`
                                // TODO: Use type switching instead?

how to use upsert ? can you give a example?

like this in java

IndexRequest indexRequest = new IndexRequest("index", "type", "1")
.source(jsonBuilder()
.startObject()
.field("name", "Joe Smith")
.field("gender", "male")
.endObject());
UpdateRequest updateRequest = new UpdateRequest("index", "type", "1")
.doc(jsonBuilder()
.startObject()
.field("gender", "male")
.endObject())
.upsert(indexRequest);
client.update(updateRequest).get();

Always hits /

func elast() error { api := snapshot.New(transport.New()) snap, err := api.GetRepository() if err != nil { return err } defer snap.Response.Body.Close() body, err := ioutil.ReadAll(snap.Response.Body) if err != nil { return err } fmt.Println(string(body)) return nil }
always returns
{ "name" : "nV2Q0j1", "cluster_name" : "elasticsearch", "cluster_uuid" : "ng6xB6B5T_e8oZpxhcw6mQ", "version" : { "number" : "5.6.11", "build_hash" : "bc3eef4", "build_date" : "2018-08-16T15:25:17.293Z", "build_snapshot" : false, "lucene_version" : "6.6.1" }, "tagline" : "You Know, for Search" }
Expected result
{ "elastic": { "type": "fs", "settings": { "compress": "true", "location": "/mnt/elastic" } } }

Standard way to get request string

I see that there is a method to get Response as string. However there is not to get request as string. Sometines it's useful for debugging.
The only way I can do it is creating a custom transport, like this:

package main

import (
	"context"
	"log"
	"net/http"
	"net/http/httputil"
	"strings"

	"github.com/elastic/go-elasticsearch"
	"github.com/elastic/go-elasticsearch/esapi"
)

type LogRequest string

type LoggerTransport struct {
	transport http.RoundTripper
}

func (t *LoggerTransport) RoundTrip(req *http.Request) (*http.Response, error) {

	lr := req.Context().Value(LogRequest("log"))
	if lr != nil && lr.(bool) == true {
		requestDump, err := httputil.DumpRequest(req, true)
		if err == nil {
			log.Printf("Request: %s", string(requestDump))
		}
	}

	return t.transport.RoundTrip(req)
}

func main() {

	log.SetFlags(0)

	es, err := elasticsearch.NewClient(elasticsearch.Config{Transport: &LoggerTransport{transport: http.DefaultTransport}})
	if err != nil {
		log.Fatalf("Error creating the client: %s", err)
	}
	
	req := esapi.IndexRequest{
		Index:      "test",
		DocumentID: "1",
		Body:       strings.NewReader(`{"title" : "` + "Test title" + `"}`),
		Refresh:    "true",
	}
	
	res, err := req.Do(context.WithValue(context.Background(), LogRequest("log"), true), es)
	if err != nil {
		log.Fatalf("Error indexing document: %s", err)
	}

	log.Printf("Response: %s", res.String())
}

Through a WithParam context selectively I log or not.
It would be possible to have another way to do this?

Thanks.

Tags for previous versions

The repository contains the only tags: v.0.0.0 and v.7.0.0-rc1.

Could you please add tags for v.6.0.0 and v.5.0.0? It'll make possible to use gopkg.in

Documentation

Hi! Where's the documentation (or it's the code itself)? Thank you!

Govendor installation problem

When I package dependencies with govendor, an error occured: "use of internal package github.com/elastic/go-elasticsearch/internal/version not allowed".How can I fix it?
Package version:elasticsearch/v6
Operating system: Mac os 10.14.1

v6 create index goroutine problem

when the number of request growing, goroutine number keeps growing.

b, _ := json.Marshal(order)

resp, err := o.es.Index(
	order.GetCertainIndex(),
	bytes.NewReader(b),
	o.es.Index.WithDocumentID(order.ID),
	o.es.Index.WithDocumentType(order.GetType()),
	o.es.Index.WithRefresh("true"))

[Panic BUG]: Client with Logger cause panic if http roundtrip return a error response!

file: estransport/estransport.go:116

	start := time.Now().UTC()
	res, err := c.transport.RoundTrip(req) // if err != nil, then res will be nil
	dur := time.Since(start)

	if c.logger != nil { // and only happen when client with logger specific
		var dupRes http.Response
		if res != nil {
			dupRes = *res
		}
		if c.logger.RequestBodyEnabled() {
			if req.Body != nil && req.Body != http.NoBody {
				req.Body = ioutil.NopCloser(dupReqBody)
			}
		}
		if c.logger.ResponseBodyEnabled() {
			if res.Body != nil && res.Body != http.NoBody { // if res == nil, will panic
				b1, b2, _ := duplicateBody(res.Body)
				dupRes.Body = b1
				res.Body = b2
			}
		}
		c.logger.LogRoundTrip(req, &dupRes, err, start, dur) // errcheck exclude
	}

Scroll API passes scroll_id in both path and body

Summary

The Scroll API takes in a scroll ID to identify subsequent pages. This scroll ID can be passed either through the URL path (POST /_search/scroll/<scroll_id>) or through the POST body ({ scroll_id: "<scroll_id>" }) per https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html.

In the case of this library, the scroll ID is passed in both the URL path and the POST body. However, this breaks the scroll API in cases where the scroll_id is too long to fit in the URL. When this happens you receive a TCP broken pipe error.

Steps to reproduce

  1. Create a cluster with > 10k shards
  2. Fire a search request with a small size and enable scrolling
  3. Use the scroll API with this extremely long scroll_id
  4. Observe the TCP broken pipe error

Remediation

Remove the scroll_id from the URL path. This is redundant and is length constrained compared to the POST body.

I believe the code is here:

if r.ScrollID != "" {
and here:
if len(r.ScrollID) > 0 {

Screen Shot 2019-05-11 at 12 03 57 AM

Provide alternative for basic auth

Including user:pass in the URL is, as we've learned from time to time on Logstash, not a safe thing to do. The reason is that you can easily make mistakes when logging such that you intend to log the URL, but that URL includes secrets, and now you've written your secrets to the log file.

Proposal: Include a way to provide credentials without embedded them into the URL string.

BUG unknown field 'Username' ,'Password' in struct literal of type elasticsearch.Config

111/main.go:34:3: unknown field 'Username' in struct literal of type elasticsearch.Config
111/main.go:35:3: unknown field 'Password' in struct literal of type elasticsearch.Config
111/main.go:36:3: unknown field 'CloudID' in struct literal of type elasticsearch.Config
111/main.go:37:3: unknown field 'APIKey' in struct literal of type elasticsearch.Config

func main() {
  config1 := elasticsearch.Config{
  Addresses: []string{
    "http://elasticsearch.aliyuncs.com:9200",
  },
  Username:  "elastic",
  Password:  "elastic1",
  CloudID:   "",
  APIKey:    "",
  Transport: &http.Transport{
    MaxIdleConnsPerHost:   10,
    ResponseHeaderTimeout: time.Second,
    DialContext:           (&net.Dialer{Timeout: time.Second}).DialContext,
    TLSClientConfig: &tls.Config{
      MinVersion: tls.VersionTLS11,
      // ...
    },
  },
    //Logger:    nil,
  }
  
  es, err := elasticsearch.NewClient(config1)
  fmt.Println(es,err)
}

Cannot use forward slash in document ID

Issue

When adding a document to Elasticsearch (v7.0.1) using go-elasticsearch on master branch, it is not possible to use the '/' as a separator within the document ID field e.g. title/test.txt.

Sample code:

func example() {
	client, _ := es.NewDefaultClient()
	docID := "title/test.txt"
	req := esapi.IndexRequest{
		Index:      "test",
		DocumentID: docID,
		Body:       strings.NewReader(`{"title" : "test.txt"}"`),
		Refresh:    "true",
	}

	res, _ := req.Do(context.Background(), client)
	defer res.Body.Close()

	if res.IsError() {
		log.Printf("[%s] Error indexing document ID=%s", res.String(), docID)
	}
}

Using curl I can insert the document by manually encoding the '/' as below:

curl -X PUT "localhost:9200/test/_doc/title%2Ftest" -H 'Content-Type: application/json' -d' 
{ 
    "title" : "test.txt" 
} 
' 

Expected

200 OK with document added to Elasticsearch.

Actual

Error produced as below:

[[400 Bad Request] {"error":"no handler found for uri [/test/_doc/title/test.txt?refresh=true] and method [PUT]"}] Error indexing document ID=title/test.txt

Root Cause?

It would seem from looking at the code that the URL is not constructed correctly. Within esapi.request.go it constructs the request as below:

func newRequest(method, path string, body io.Reader) (*http.Request, error) {
	r := http.Request{
		Method:     method,
		URL:        &url.URL{Path: path},
		Proto:      "HTTP/1.1",
		ProtoMajor: 1,
		ProtoMinor: 1,
		Header:     make(http.Header),
	}
  ...

The path, specifically the document ID part, does not get encoded and the URL structure is not initialised correctly, meaning the necessary RawPath field is not set. In order to resolve this issue, the document ID would need to be encoded prior to use and the URL should be initialised using the url.Parse(path) correctly setting Path and RawPath fields.

Add examples for using basic auth and custom headers

While pairing with @Dr-Syn on using this package, we found that basic auth seems to be not yet documented?

For basic auth:

  • Scanning the code gives the feeling that including the user:pass in the Addresses list works for this purpose

For custom headers

  • It's also useful sometimes to add custom headers, for example, with es-security-runas-user or for passing other credential headers (JWT tokens, Cookies, etc).

mget 503 error

mget error 503 ,but no any words.
image

I test data by postman . it is ok。
image

Can not index to elasticsearch

Hi,
I'm new to go lang.
I was trying to use your library to index some events into elasticsearch with this code.
It did create the test index on elasticsearch cluster but did not index any events into it and returned this error: "400 Bad Request"
Please tell me what is wrong? This is my code:

package main

import (
   "context"
   "fmt"
   "github.com/elastic/go-elasticsearch"
   "github.com/elastic/go-elasticsearch/esapi"
   "io/ioutil"
   "net/http"
   "strconv"
   "strings"
   "testing"
)

var defaultResponse = http.Response{
   Status:        "200 OK",
   StatusCode:    200,
   ContentLength: 2,
   Header:        http.Header(map[string][]string{"Content-Type": {"application/json"}}),
   Body:          ioutil.NopCloser(strings.NewReader(`{}`)),
}

type FakeTransport struct {
   FakeResponse *http.Response
}

func newFakeTransport(b *testing.B) *FakeTransport {
   return &FakeTransport{FakeResponse: &defaultResponse}
}

func main() {
   ctx := context.Background()

   client, err := elasticsearch.NewClient(elasticsearch.Config{
      Addresses: []string{"http://127.0.0.1:9200"},
   })
   if err != nil {
      fmt.Println("ERROR: %s", err)
   }
   var body strings.Builder

   for i := 0; i < 100; i++ {
      docID := strconv.FormatInt(int64(i), 10)

      body.Reset()
      body.WriteString(`{"foo" : "bar `)
      body.WriteString(docID)
      body.WriteString(` " }`)

      req := esapi.IndexRequest{
         Index:      "test",
         DocumentID: docID,
         Body:       strings.NewReader(body.String()),
         Refresh:    "true",
         Pretty:     true,
         Timeout:    100,
      }
      if _, err := req.Do(ctx, client); err != nil {
         fmt.Println("Unexpected error when getting a response: %s", err)
      }
   }
}

Thanks!

Pending items for v1

generator/api

  • figure out how we end up with the wrong package name in some cases (do.tmpl)
  • add typed accessors and/or fields to structured responses (e.g., to api.IndexResponse). Changes should go to generator/api/templates/method.tmpl
  • handle multiple HTTP methods in index
  • render bulk and dict types in Param.String()

client

  • we should find a trick to link to api from client in godoc, so people can see the API methods embedded in client.Client more clearly
  • support additional client options (client/option.go)

generator/test

  • resolve variables set by set before using them in other actions (right now they stay as $<var>)
  • implement catch et al
  • implement regex matching in generator/test/action/match.go
  • implement generator/test/action/skip.go to skip tests
  • keep raw name for test as comment to test (testcase.go/test.tmpl)

Cleanup:

  • remove t.Skip() in test.tmpl
  • handle variables that are declared and not used in test.tmpl (still an issue after all other TODOs?)

Nits:

  • make type code in param.go its own type
  • the code in generator/test/util_test.go should be shared with the generator/api package.

es.scroll() sample

Hi,
I am trying to find a sample code to use scan() or scroll() api in the client, that would fetch paginated results from ES.
Can someone please point me to the reference on how to use that ?

Ability to add date range to indices in search api

Do we have the ability to search my ES indices based on date-range/DateMath ?

For example, if I have ES indices of format test-<data_format> and I want to search data across specific indices, for example now-10d to now.

Is this case feasible using this package ?

Add response types

elasticsearch.Client.Get() returns *Response, error

Most responses in Elasticsearch will have at least a top-level predictable response structure. It'd be nice, for example, if Get() returned something like a GetResponse.

The workaround is roughly the following for every kind of response:

var getResponse struct {
  Index string `json:"_index"`
  ID string `json:"_id"`
  // a dozen other lines
}

err = json.NewDecoder(response.Body).Decode(&getResponse)
...
// do something with getResponse

Thoughts? Maybe I'm missing something in the docs, but it'd be very nice not to have to define response type structs all over the place.

Retry option in go-elasticsearch

I want to implement the retry of the connection to elasticsearch. But I could not find any proper documentation or sample snippet regarding the issue.
Can someone please guide how to implement retry feature.

Function WithHosts commented

I downloaded the code to perform tests and added the code that is in the README.

The following error appears:

undefined: client.WithHosts
cannot use body (type map[string]interface {}) as type api.SearchOption in argument to c.API.Search

I open the code in options.go in the client folder and I see that it is commented.

Can you put an example that works in the README? Or tell me where I can find how to run it.

Thank you.

Regards,
Natalia.

timeout 参数 BUG

使用超时选项,s.client.Search(s.client.Search.WithIndex("index"), s.client.Search.WithBody(body), s.client.Search.WithTimeout(180000))
生成的请求URL为:
/index/_search?timeout=3m0s
ES 6.4 版本不能解析timeout参数,响应的错误信息为:
"reason": "failed to parse [3m0s]"
请求URL修改为 /index/_search?timeout=3m 则可以正常工作。
希望可以帮助到你们。

import failed

unknown import path "github.com/elastic/go-elasticsearch/v6": cannot find package

dial tcp IP:PORT: i/o timeout

When I use this vendor to connect elasticsearch 2.x, It's error, I know it's support for 7.x now, but it's no error when I doing NewClient, then I use client.Info(), it's nil, and the error is dial tcp IP:PORT: i/o timeout.

Query DSL support

It'd be great to avoid handling huge strings.Builder for Search queries.
Is a functional client similar to the one in olivere/elastic in the roadmap and, if so, what is the timeline for this feature?

No docker container for 7.x

I know the client targets 7.x of elasticsearch, but there aren't even any official docker images for elasticsearch 7.x

Kind of a big miss not to support ES 6 before ES7 is even readily available.

esapi.newRequest doesn't set Body when using esutil.JSONReader

newRequest only sets the body for specific types, as seen below. There should be a fallback for other io.Reader types.

if body != nil {
switch b := body.(type) {
case *bytes.Buffer:
r.Body = ioutil.NopCloser(body)
r.ContentLength = int64(b.Len())
case *bytes.Reader:
r.Body = ioutil.NopCloser(body)
r.ContentLength = int64(b.Len())
case *strings.Reader:
r.Body = ioutil.NopCloser(body)
r.ContentLength = int64(b.Len())
}
}

Work in Progress?

This seems to be WIP for last year. Is there some deadline on when it will be ready for production use?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.