[
  {
    "path": ".github/workflows/codeql-v7.yml",
    "content": "name: \"Code scanning - action\"\n\non:\n  push:\n    branches:\n      - '*.v7'\n  pull_request:\n    branches:\n      - '*.v7'\n  schedule:\n    - cron: '0 19 * * 3'\n\njobs:\n  codeql:\n    strategy:\n      matrix:\n        go: [stable]\n        os: [ubuntu-latest]\n    name: Run ${{ matrix.go }} on ${{ matrix.os }}\n    runs-on: ${{ matrix.os }}\n    steps:\n    - name: Prepare tests\n      run: |\n        sudo apt-get install -y netcat\n        sudo sysctl -w vm.max_map_count=262144\n\n    - name: Setup Go ${{ matrix.go }}\n      uses: actions/setup-go@v5\n      with:\n        go-version: ${{ matrix.go }}\n\n    - name: Checkout repository\n      uses: actions/checkout@v4\n      with:\n        fetch-depth: 2\n\n    - uses: actions/cache@v4\n      with:\n        path: |\n          ~/.cache/go-build\n          ~/go/pkg/mod\n        key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}\n        restore-keys: |\n          ${{ runner.os }}-go-\n\n    - name: Initialize CodeQL\n      uses: github/codeql-action/init@v1\n      with:\n        languages: go\n\n    - name: Run Docker containers\n      run: docker compose up -d\n\n    - name: Check Docker containers\n      run: docker ps -a\n\n    - name: Get dependencies\n      run: |\n        go get -u github.com/google/go-cmp/cmp\n        go get -u github.com/fortytw2/leaktest\n        go get . ./aws/... ./config/... ./trace/... ./uritemplates/...\n\n    - name: Wait for Elasticsearch\n      run: |\n        while ! nc -z localhost 9200; do sleep 1; done\n        while ! nc -z localhost 9210; do sleep 1; done\n        sleep 5\n\n    - name: Run the tests\n      run: |\n        go test -race -deprecations -strict-decoder -v . ./aws/... ./config/... ./trace/... ./uritemplates/...\n    - name: Perform CodeQL Analysis\n      uses: github/codeql-action/analyze@v1\n"
  },
  {
    "path": ".github/workflows/test-v7.yml",
    "content": "on:\n  push:\n    branches:\n      - '*.v7'\n  pull_request:\n    branches:\n      - '*.v7'\nname: Test v7\njobs:\n  test:\n    strategy:\n      matrix:\n        go: [stable]\n        os: [ubuntu-latest]\n    name: Run ${{ matrix.go }} on ${{ matrix.os }}\n    runs-on: ${{ matrix.os }}\n    steps:\n    - name: Prepare tests\n      run: |\n        sudo apt-get install -y netcat\n        sudo sysctl -w vm.max_map_count=262144\n\n    - name: Setup Go ${{ matrix.go }}\n      uses: actions/setup-go@v5\n      with:\n        go-version: ${{ matrix.go }}\n\n    - name: Checkout code\n      uses: actions/checkout@v4\n\n    - uses: actions/cache@v4\n      with:\n        path: |\n          ~/.cache/go-build\n          ~/go/pkg/mod\n        key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}\n        restore-keys: |\n          ${{ runner.os }}-go-\n\n    - name: Run Docker containers\n      run: docker compose up -d\n\n    - name: Check Docker containers\n      run: docker ps -a\n\n    - name: Get dependencies\n      run: |\n        go get -u github.com/google/go-cmp/cmp\n        go get -u github.com/fortytw2/leaktest\n        go get . ./aws/... ./config/... ./trace/... ./uritemplates/...\n\n    - name: Wait for Elasticsearch\n      run: |\n        while ! nc -z localhost 9200; do sleep 1; done\n        while ! nc -z localhost 9210; do sleep 1; done\n\n    - name: Run the tests\n      run: |\n        go test -race -deprecations -strict-decoder -v . ./aws/... ./config/... ./trace/... ./uritemplates/...\n"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture specific extensions/prefixes\n*.[568vq]\n[568vq].out\n\n*.cgo1.go\n*.cgo2.c\n_cgo_defun.c\n_cgo_gotypes.go\n_cgo_export.*\n\n_testmain.go\n\n*.exe\n\n.envrc\n\n/.vscode/\n/.idea/\n/data\n/debug.test\n/generator\n/cluster-test/cluster-test\n/cluster-test/*.log\n/cluster-test/es-chaos-monkey\n/dist\n/go.sum\n/spec\n/tmp\n/CHANGELOG-3.0.html\n"
  },
  {
    "path": "CHANGELOG-3.0.md",
    "content": "# Elastic 3.0\n\nElasticsearch 2.0 comes with some [breaking changes](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/breaking-changes-2.0.html). You will probably need to upgrade your application and/or rewrite part of it due to those changes.\n\nWe use that window of opportunity to also update Elastic (the Go client) from version 2.0 to 3.0. This will introduce both changes due to the Elasticsearch 2.0 update as well as changes that make Elastic cleaner by removing some old cruft.\n\nSo, to summarize:\n\n1. Elastic 2.0 is compatible with Elasticsearch 1.7+ and is still actively maintained.\n2. Elastic 3.0 is compatible with Elasticsearch 2.0+ and will soon become the new master branch.\n\nThe rest of the document is a list of all changes in Elastic 3.0.\n\n## Pointer types\n\nAll types have changed to be pointer types, not value types. This not only is cleaner but also simplifies the API as illustrated by the following example:\n\nExample for Elastic 2.0 (old):\n\n```go\nq := elastic.NewMatchAllQuery()\nres, err := elastic.Search(\"one\").Query(&q).Do()  // notice the & here\n```\n\nExample for Elastic 3.0 (new):\n\n```go\nq := elastic.NewMatchAllQuery()\nres, err := elastic.Search(\"one\").Query(q).Do()   // no more &\n// ... which can be simplified as:\nres, err := elastic.Search(\"one\").Query(elastic.NewMatchAllQuery()).Do()\n```\n\nIt also helps to prevent [subtle issues](https://github.com/olivere/elastic/issues/115#issuecomment-130753046).\n\n## Query/filter merge\n\nOne of the biggest changes in Elasticsearch 2.0 is the [merge of queries and filters](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_query_dsl_changes.html#_queries_and_filters_merged). In Elasticsearch 1.x, you had a whole range of queries and filters that were basically identical (e.g. `term_query` and `term_filter`).\n\nThe practical aspect of the merge is that you can now basically use queries where once you had to use filters instead. For Elastic 3.0 this means: We could remove a whole bunch of files. Yay!\n\nNotice that some methods still come by \"filter\", e.g. `PostFilter`. However, they accept a `Query` now when they used to accept a `Filter` before.\n\nExample for Elastic 2.0 (old):\n\n```go\nq := elastic.NewMatchAllQuery()\nf := elastic.NewTermFilter(\"tag\", \"important\")\nres, err := elastic.Search().Index(\"one\").Query(&q).PostFilter(f)\n```\n\nExample for Elastic 3.0 (new):\n\n```go\nq := elastic.NewMatchAllQuery()\nf := elastic.NewTermQuery(\"tag\", \"important\") // it's a query now!\nres, err := elastic.Search().Index(\"one\").Query(q).PostFilter(f)\n```\n\n## Facets are removed\n\n[Facets have been removed](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_removed_features.html#_facets_have_been_removed) in Elasticsearch 2.0. You need to use aggregations now.\n\n## Errors\n\nElasticsearch 2.0 returns more information about an error in the HTTP response body. Elastic 3.0 now reads this information and makes it accessible by the consumer.\n\nErrors and all its details are now returned in [`Error`](https://github.com/olivere/elastic/blob/release-branch.v3/errors.go#L59).\n\n### HTTP Status 404 (Not Found)\n\nWhen Elasticsearch does not find an entity or an index, it generally returns HTTP status code 404. In Elastic 2.0 this was a valid result and didn't raise an error from the `Do` functions. This has now changed in Elastic 3.0.\n\nStarting with Elastic 3.0, there are only two types of responses considered successful. First, responses with HTTP status codes [200..299]. Second, HEAD requests which return HTTP status 404. The latter is used by Elasticsearch to e.g. check for existence of indices or documents. All other responses will return an error.\n\nTo check for HTTP Status 404 (with non-HEAD requests), e.g. when trying to get or delete a missing document, you can use the [`IsNotFound`](https://github.com/olivere/elastic/blob/release-branch.v3/errors.go#L84) helper (see below).\n\nThe following example illustrates how to check for a missing document in Elastic 2.0 and what has changed in 3.0.\n\nExample for Elastic 2.0 (old):\n\n```go\nres, err = client.Get().Index(\"one\").Type(\"tweet\").Id(\"no-such-id\").Do()\nif err != nil {\n  // Something else went wrong (but 404 is NOT an error in Elastic 2.0)\n}\nif !res.Found {\n\t// Document has not been found\n}\n```\n\nExample for Elastic 3.0 (new):\n\n```go\nres, err = client.Get().Index(\"one\").Type(\"tweet\").Id(\"no-such-id\").Do()\nif err != nil {\n  if elastic.IsNotFound(err) {\n    // Document has not been found\n  } else {\n    // Something else went wrong\n  }\n}\n```\n\n### HTTP Status 408 (Timeouts)\n\nElasticsearch now responds with HTTP status code 408 (Timeout) when a request fails due to a timeout. E.g. if you specify a timeout with the Cluster Health API, the HTTP response status will be 408 if the timeout is raised. See [here](https://github.com/elastic/elasticsearch/commit/fe3179d9cccb569784434b2135ca9ae13d5158d3) for the specific commit to the Cluster Health API.\n\nTo check for HTTP Status 408, we introduced the [`IsTimeout`](https://github.com/olivere/elastic/blob/release-branch.v3/errors.go#L101) helper.\n\nExample for Elastic 2.0 (old):\n\n```go\nhealth, err := client.ClusterHealth().WaitForStatus(\"yellow\").Timeout(\"1s\").Do()\nif err != nil {\n  // ...\n}\nif health.TimedOut {\n  // We have a timeout\n}\n```\n\nExample for Elastic 3.0 (new):\n\n```go\nhealth, err := client.ClusterHealth().WaitForStatus(\"yellow\").Timeout(\"1s\").Do()\nif elastic.IsTimeout(err) {\n  // We have a timeout\n}\n```\n\n### Bulk Errors\n\nThe error response of a bulk operation used to be a simple string in Elasticsearch 1.x.\nIn Elasticsearch 2.0, it returns a structured JSON object with a lot more details about the error.\nThese errors are now captured in an object of type [`ErrorDetails`](https://github.com/olivere/elastic/blob/release-branch.v3/errors.go#L59) which is used in [`BulkResponseItem`](https://github.com/olivere/elastic/blob/release-branch.v3/bulk.go#L206).\n\n### Removed specific Elastic errors\n\nThe specific error types `ErrMissingIndex`, `ErrMissingType`, and `ErrMissingId` have been removed. They were only used by `DeleteService` and are replaced by a generic error message.\n\n## Numeric types\n\nElastic 3.0 has settled to use `float64` everywhere. It used to be a mix of `float32` and `float64` in Elastic 2.0. E.g. all boostable queries in Elastic 3.0 now have a boost type of `float64` where it used to be `float32`.\n\n## Pluralization\n\nSome services accept zero, one or more indices or types to operate on.\nE.g. in the `SearchService` accepts a list of zero, one, or more indices to\nsearch and therefor had a func called `Index(index string)` and a func\ncalled `Indices(indices ...string)`.\n\nElastic 3.0 now only uses the singular form that, when applicable, accepts a\nvariadic type. E.g. in the case of the `SearchService`, you now only have\none func with the following signature: `Index(indices ...string)`.\n\nNotice this is only limited to `Index(...)` and `Type(...)`. There are other\nservices with variadic functions. These have not been changed.\n\n## Multiple calls to variadic functions\n\nSome services with variadic functions have cleared the underlying slice when\ncalled while other services just add to the existing slice. This has now been\nnormalized to always add to the underlying slice.\n\nExample for Elastic 2.0 (old):\n\n```go\n// Would only cleared scroll id \"two\"\n// because ScrollId cleared the values when called multiple times\nclient.ClearScroll().ScrollId(\"one\").ScrollId(\"two\").Do()\n```\n\nExample for Elastic 3.0 (new):\n\n```go\n// Now (correctly) clears both scroll id \"one\" and \"two\"\n// because ScrollId no longer clears the values when called multiple times\nclient.ClearScroll().ScrollId(\"one\").ScrollId(\"two\").Do()\n```\n\n## Ping service requires URL\n\nThe `Ping` service raised some issues because it is different from all\nother services. If not explicitly given a URL, it always pings `127.0.0.1:9200`.\n\nUsers expected to ping the cluster, but that is not possible as the cluster\ncan be a set of many nodes: So which node do we ping then?\n\nTo make it more clear, the `Ping` function on the client now requires users\nto explicitly set the URL of the node to ping.\n\n## Meta fields\n\nMany of the meta fields e.g. `_parent` or `_routing` are now\n[part of the top-level of a document](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_mapping_changes.html#migration-meta-fields)\nand are no longer returned as parts of the `fields` object. We had to change\nlarger parts of e.g. the `Reindexer` to get it to work seamlessly with Elasticsearch 2.0.\n\nNotice that all stored meta-fields are now [returned by default](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_crud_and_routing_changes.html#_all_stored_meta_fields_returned_by_default).\n\n## HasParentQuery / HasChildQuery\n\n`NewHasParentQuery` and `NewHasChildQuery` must now include both parent/child type and query. It is now in line with the Java API.\n\nExample for Elastic 2.0 (old):\n\n```go\nallQ := elastic.NewMatchAllQuery()\nq := elastic.NewHasChildFilter(\"tweet\").Query(&allQ)\n```\n\nExample for Elastic 3.0 (new):\n\n```go\nq := elastic.NewHasChildQuery(\"tweet\", elastic.NewMatchAllQuery())\n```\n\n## SetBasicAuth client option\n\nYou can now tell Elastic to pass HTTP Basic Auth credentials with each request. In previous versions of Elastic you had to set up your own `http.Transport` to do this. This should make it more convenient to use Elastic in combination with [Shield](https://www.elastic.co/products/shield) in its [basic setup](https://www.elastic.co/guide/en/shield/current/enable-basic-auth.html).\n\nExample:\n\n```go\nclient, err := elastic.NewClient(elastic.SetBasicAuth(\"user\", \"secret\"))\nif err != nil {\n  log.Fatal(err)\n}\n```\n\n## Delete-by-Query API\n\nThe Delete-by-Query API is [a plugin now](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_removed_features.html#_delete_by_query_is_now_a_plugin). It is no longer core part of Elasticsearch. You can [install it as a plugin as described here](https://www.elastic.co/guide/en/elasticsearch/plugins/2.0/plugins-delete-by-query.html).\n\nElastic 3.0 still contains the `DeleteByQueryService`, but you need to install the plugin first. If you don't install it and use `DeleteByQueryService` you will most probably get a 404.\n\nAn older version of this document stated the following:\n\n> Elastic 3.0 still contains the `DeleteByQueryService` but it will fail with `ErrPluginNotFound` when the plugin is not installed.\n>\n> Example for Elastic 3.0 (new):\n>\n> ```go\n> _, err := client.DeleteByQuery().Query(elastic.NewTermQuery(\"client\", \"1\")).Do()\n> if err == elastic.ErrPluginNotFound {\n> \t// Delete By Query API is not available\n> }\n> ```\n\nI have decided that this is not a good way to handle the case of a missing plugin. The main reason is that with this logic, you'd always have to check if the plugin is missing in case of an error. This is not only slow, but it also puts logic into a service where it should really be just opaque and return the response of Elasticsearch.\n\nIf you rely on certain plugins to be installed, you should check on startup. That's where the following two helpers come into play.\n\n## HasPlugin and SetRequiredPlugins\n\nSome of the core functionality of Elasticsearch has now been moved into plugins. E.g. the Delete-by-Query API is [a plugin now](https://www.elastic.co/guide/en/elasticsearch/plugins/2.0/plugins-delete-by-query.html).\n\nYou need to make sure to add these plugins to your Elasticsearch installation to still be able to use the `DeleteByQueryService`. You can test this now with the `HasPlugin(name string)` helper in the client.\n\nExample for Elastic 3.0 (new):\n\n```go\nerr, found := client.HasPlugin(\"delete-by-query\")\nif err == nil && found {\n\t// ... Delete By Query API is available\n}\n```\n\nTo simplify this process, there is now a `SetRequiredPlugins` helper that can be passed as an option func when creating a new client. If the plugin is not installed, the client wouldn't be created in the first place.\n\n```go\n// Will raise an error if the \"delete-by-query\" plugin is NOT installed\nclient, err := elastic.NewClient(elastic.SetRequiredPlugins(\"delete-by-query\"))\nif err != nil {\n  log.Fatal(err)\n}\n```\n\nNotice that there also is a way to define [mandatory plugins](https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-plugins.html#_mandatory_plugins) in the Elasticsearch configuration file.\n\n## Common Query has been renamed to Common Terms Query\n\nThe `CommonQuery` has been renamed to `CommonTermsQuery` to be in line with the [Java API](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_java_api_changes.html#_query_filter_refactoring).\n\n## Remove `MoreLikeThis` and `MoreLikeThisField`\n\nThe More Like This API and the More Like This Field query [have been removed](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_query_dsl_changes.html#_more_like_this) and replaced with the `MoreLikeThisQuery`.\n\n## Remove Filtered Query\n\nWith the merge of queries and filters, the [filtered query became deprecated](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_query_dsl_changes.html#_literal_filtered_literal_query_and_literal_query_literal_filter_deprecated). While it is only deprecated and therefore still available in Elasticsearch 2.0, we have decided to remove it from Elastic 3.0. Why? Because we think that when you're already forced to rewrite many of your application code, it might be a good chance to get rid of things that are deprecated as well. So you might simply change your filtered query with a boolean query as [described here](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_query_dsl_changes.html#_literal_filtered_literal_query_and_literal_query_literal_filter_deprecated).\n\n## Remove FuzzyLikeThis and FuzzyLikeThisField\n\nBoth have been removed from Elasticsearch 2.0 as well.\n\n## Remove LimitFilter\n\nThe `limit` filter is [deprecated in Elasticsearch 2.0](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_query_dsl_changes.html#_literal_limit_literal_filter_deprecated) and becomes a no-op. Now is a good chance to remove it from your application as well. Use the `terminate_after` parameter in your search [as described here](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/search-request-body.html) to achieve similar effects.\n\n## Remove `_cache` and `_cache_key` from filters\n\nBoth have been [removed from Elasticsearch 2.0 as well](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_query_dsl_changes.html#_filter_auto_caching).\n\n## Partial fields are gone\n\nPartial fields are [removed in Elasticsearch 2.0](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/_search_changes.html#_partial_fields) in favor of [source filtering](https://www.elastic.co/guide/en/elasticsearch/reference/2.0/search-request-source-filtering.html).\n\n## Scripting\n\nA [`Script`](https://github.com/olivere/elastic/blob/release-branch.v3/script.go) type has been added to Elastic 3.0. In Elastic 2.0, there were various places (e.g. aggregations) where you could just add the script as a string, specify the scripting language, add parameters etc. With Elastic 3.0, you should now always use the `Script` type.\n\nExample for Elastic 2.0 (old):\n\n```go\nupdate, err := client.Update().Index(\"twitter\").Type(\"tweet\").Id(\"1\").\n\tScript(\"ctx._source.retweets += num\").\n\tScriptParams(map[string]interface{}{\"num\": 1}).\n\tUpsert(map[string]interface{}{\"retweets\": 0}).\n\tDo()\n```\n\nExample for Elastic 3.0 (new):\n\n```go\nupdate, err := client.Update().Index(\"twitter\").Type(\"tweet\").Id(\"1\").\n\tScript(elastic.NewScript(\"ctx._source.retweets += num\").Param(\"num\", 1)).\n\tUpsert(map[string]interface{}{\"retweets\": 0}).\n\tDo()\n```\n\n## Cluster State\n\nThe combination of `Metric(string)` and `Metrics(...string)` has been replaced by a single func with the signature `Metric(...string)`.\n\n## Unexported structs in response\n\nServices generally return a typed response from a `Do` func. Those structs are exported so that they can be passed around in your own application. In Elastic 3.0 however, we changed that (most) sub-structs are now unexported, meaning: You can only pass around the whole response, not sub-structures of it. This makes it easier for restructuring responses according to the Elasticsearch API. See [`ClusterStateResponse`](https://github.com/olivere/elastic/blob/release-branch.v3/cluster_state.go#L182) as an example.\n\n## Add offset to Histogram aggregation\n\nHistogram aggregations now have an [offset](https://github.com/elastic/elasticsearch/pull/9505) option.\n\n## Services\n\n### REST API specification\n\nAs you might know, Elasticsearch comes with a REST API specification. The specification describes the endpoints in a JSON structure.\n\nMost services in Elastic predated the REST API specification. We are in the process of bringing all these services in line with the specification. Services can be generated by `go generate` (not 100% automatic though). This is an ongoing process.\n\nThis probably doesn't mean a lot to you. However, you can now be more confident that Elastic supports all features that the REST API specification describes.\n\nAt the same time, the file names of the services are renamed to match the REST API specification naming.\n\n### REST API Test Suite\n\nThe REST API specification of Elasticsearch comes along with a test suite that official clients typically use to test for conformance. Up until now, Elastic didn't run this test suite. However, we are in the process of setting up infrastructure and tests to match this suite as well.\n\nThis process in not completed though.\n\n\n"
  },
  {
    "path": "CHANGELOG-5.0.md",
    "content": "# Changes in Elastic 5.0\n\n## Enforce context.Context in PerformRequest and Do\n\nWe enforce the usage of `context.Context` everywhere you execute a request.\nYou need to change all your `Do()` calls to pass a context: `Do(ctx)`.\nThis enables automatic request cancelation and many other patterns.\n\nIf you don't need this, simply pass `context.TODO()` or `context.Background()`.\n\n## Warmers removed\n\nWarmers are no longer necessary and have been [removed in ES 5.0](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_index_apis.html#_warmers).\n\n## Optimize removed\n\nOptimize was deprecated in ES 2.0 and has been [removed in ES 5.0](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_rest_api_changes.html#_literal__optimize_literal_endpoint_removed).\nUse [Force Merge](https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-forcemerge.html) instead.\n\n## Missing Query removed\n\nThe `missing` query has been [removed](https://www.elastic.co/guide/en/elasticsearch/reference/master/query-dsl-exists-query.html#_literal_missing_literal_query).\nUse `exists` query with `must_not` in `bool` query instead.\n\n## And Query removed\n\nThe `and` query has been [removed](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_search_changes.html#_deprecated_queries_removed).\nUse `must` clauses in a `bool` query instead.\n\n## Not Query removed\n\nTODO Is it removed?\n\n## Or Query removed\n\nThe `or` query has been [removed](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_search_changes.html#_deprecated_queries_removed).\nUse `should` clauses in a `bool` query instead.\n\n## Filtered Query removed\n\nThe `filtered` query has been [removed](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_search_changes.html#_deprecated_queries_removed).\nUse `bool` query instead, which supports `filter` clauses too.\n\n## Limit Query removed\n\nThe `limit` query has been [removed](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_search_changes.html#_deprecated_queries_removed).\nUse the `terminate_after` parameter instead.\n\n# Template Query removed\n\nThe `template` query has been [deprecated](https://www.elastic.co/guide/en/elasticsearch/reference/5.x/query-dsl-template-query.html). You should use\nSearch Templates instead.\n\nWe remove it from Elastic 5.0 as the 5.0 update is already a good opportunity\nto get rid of old stuff.\n\n## `_timestamp` and `_ttl` removed\n\nBoth of these fields were deprecated and are now [removed](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_mapping_changes.html#_literal__timestamp_literal_and_literal__ttl_literal).\n\n## Search template Put/Delete API returns `acknowledged` only\n\nThe response type for Put/Delete search templates has changed.\nIt only returns a single `acknowledged` flag now.\n\n## Fields has been renamed to Stored Fields\n\nThe `fields` parameter has been renamed to `stored_fields`.\nSee [here](https://www.elastic.co/guide/en/elasticsearch/reference/5.x/breaking_50_search_changes.html#_literal_fields_literal_parameter).\n\n## Fielddatafields has been renamed to Docvaluefields\n\nThe `fielddata_fields` parameter [has been renamed](https://www.elastic.co/guide/en/elasticsearch/reference/5.x/breaking_50_search_changes.html#_literal_fielddata_fields_literal_parameter)\nto `docvalue_fields`.\n\n## Type exists endpoint changed\n\nThe endpoint for checking whether a type exists has been changed from\n`HEAD {index}/{type}` to `HEAD {index}/_mapping/{type}`.\nSee [here](https://www.elastic.co/guide/en/elasticsearch/reference/5.0/breaking_50_rest_api_changes.html#_literal_head_index_type_literal_replaced_with_literal_head_index__mapping_type_literal).\n\n## Refresh parameter changed\n\nThe `?refresh` parameter previously could be a boolean value. It indicated\nwhether changes made by a request (e.g. by the Bulk API) should be immediately\nvisible in search, or not. Using `refresh=true` had the positive effect of\nimmediately seeing the changes when searching; the negative effect is that\nit is a rather big performance hit.\n\nWith 5.0, you now have the choice between these 3 values.\n\n* `\"true\"` - Refresh immediately\n* `\"false\"` - Do not refresh (the default value)\n* `\"wait_for\"` - Wait until ES made the document visible in search\n\nSee [?refresh](https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-refresh.html) in the documentation.\n\nNotice that `true` and `false` (the boolean values) are no longer available\nnow in Elastic. You must use a string instead, with one of the above values.\n\n## ReindexerService removed\n\nThe `ReindexerService` was a custom solution that was started in the ES 1.x era\nto automate reindexing data, from one index to another or even between clusters.\n\nES 2.3 introduced its own [Reindex API](https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-reindex.html)\nso we're going to remove our custom solution and ask you to use the native reindexer.\n\nThe `ReindexService` is available via `client.Reindex()` (which used to point\nto the custom reindexer).\n\n## Delete By Query back in core\n\nThe [Delete By Query API](https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-delete-by-query.html)\nwas moved into a plugin in 2.0. Now its back in core with a complete rewrite based on the Bulk API.\n\nIt has it's own endpoint at `/_delete_by_query`.\n\nDelete By Query, Reindex, and Update By Query are very similar under the hood.\n\n## Reindex, Delete By Query, and Update By Query response changed\n\nThe response from the above APIs changed a bit. E.g. the `retries` value\nused to be an `int64` and returns separate values for `bulk` and `search` now:\n\n```\n// Old\n{\n    ...\n    \"retries\": 123,\n    ...\n}\n```\n\n```\n// New\n{\n    ...\n    \"retries\": {\n        \"bulk\": 123,\n        \"search\": 0\n    },\n    ...\n}\n```\n\n## ScanService removed\n\nThe `ScanService` is removed. Use the (new) `ScrollService` instead.\n\n## New ScrollService\n\nThere was confusion around `ScanService` and `ScrollService` doing basically\nthe same. One was returning slices and didn't support all query details, the\nother returned one document after another and wasn't safe for concurrent use.\nSo we merged the two and merged it into a new `ScrollService` that\nremoves all the problems with the older services.\n\nIn other words:\nIf you used `ScanService`, switch to `ScrollService`.\nIf you used the old `ScrollService`, you might need to fix some things but\noverall it should just work.\n\nChanges:\n- We replaced `elastic.EOS` with `io.EOF` to indicate the \"end of scroll\".\n\nTODO Not implemented yet\n\n## Suggesters\n\nThey have been [completely rewritten in ES 5.0](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_suggester.html).\n\nSome changes:\n- Suggesters no longer have an [output](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_suggester.html#_simpler_completion_indexing).\n\nTODO Fix all structural changes in suggesters\n\n## Percolator\n\nPercolator has [changed considerably](https://www.elastic.co/guide/en/elasticsearch/reference/5.x/breaking_50_percolator.html).\n\nElastic 5.0 adds the new\n[Percolator Query](https://www.elastic.co/guide/en/elasticsearch/reference/5.x/query-dsl-percolate-query.html)\nwhich can be used in combination with the new\n[Percolator type](https://www.elastic.co/guide/en/elasticsearch/reference/5.x/percolator.html).\n\nThe Percolate service is removed from Elastic 5.0.\n\n## Remove Consistency, add WaitForActiveShards\n\nThe `consistency` parameter has been removed in a lot of places, e.g. the Bulk,\nIndex, Delete, Delete-by-Query, Reindex, Update, and Update-by-Query API.\n\nIt has been replaced by a somewhat similar `wait_for_active_shards` parameter.\nSee https://github.com/elastic/elasticsearch/pull/19454.\n"
  },
  {
    "path": "CHANGELOG-6.0.md",
    "content": "# Changes from 5.0 to 6.0\n\nSee [breaking changes](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-6.0.html).\n\n## _all removed\n\n6.0 has removed support for the `_all` field.\n\n## Boolean values coerced\n\nOnly use `true` or `false` for boolean values, not `0` or `1` or `on` or `off`.\n\n## Single Type Indices\n\nNotice that 6.0 and future versions will default to single type indices, i.e. you may not use multiple types when e.g. adding an index with a mapping.\n\nSee [here for details](https://www.elastic.co/guide/en/elasticsearch/reference/6.7/removal-of-types.html#_what_are_mapping_types).\n\n"
  },
  {
    "path": "CHANGELOG-7.0.md",
    "content": "# Changes from 6.0 to 7.0\n\nSee [breaking changes](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/breaking-changes-7.0.html).\n\n## SearchHit.Source changed from `*json.RawMessage` to `json.RawMessage`\n\nThe `SearchHit` structure changed from\n\n```\n// SearchHit is a single hit.\ntype SearchHit struct {\n\t...\n\tSource         *json.RawMessage               `json:\"_source,omitempty\"`         // stored document source\n\t...\n}\n```\n\nto\n\n```\n// SearchHit is a single hit.\ntype SearchHit struct {\n\t...\n\tSource         json.RawMessage                `json:\"_source,omitempty\"`         // stored document source\n\t...\n}\n```\n\nAs `json.RawMessage` is a `[]byte`, there is no need to specify it\nas `*json.RawMessage` as `json.RawMessage` is perfectly ok to represent\na `nil` value.\n\nSo when deserializing the search hits, you need to change your code from:\n\n```\nfor _, hit := range searchResult.Hits.Hits {\n    var doc Doc\n    err := json.Unmarshal(*hit.Source, &doc) // notice the * here\n    if err != nil {\n        // Deserialization failed\n    }\n}\n```\n\nto\n\n```\nfor _, hit := range searchResult.Hits.Hits {\n    var doc Doc\n    err := json.Unmarshal(hit.Source, &doc) // it's missing here\n    if err != nil {\n        // Deserialization failed\n    }\n}\n```\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at oliver@eilhard.net. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to contribute\n\nElastic is an open-source project and we are looking forward to each\ncontribution.\n\nNotice that while the [official Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) is rather good, it is a high-level\noverview of the features of Elasticsearch. However, Elastic tries to resemble\nthe Java API of Elasticsearch which you can find [on GitHub](https://github.com/elastic/elasticsearch).\n\nThis explains why you might think that some options are strange or missing\nin Elastic, while often they're just different. Please check the Java API first.\n\nHaving said that: Elasticsearch is moving fast and it might be very likely\nthat we missed some features or changes. Feel free to change that.\n\n## Your Pull Request\n\nTo make it easy to review and understand your changes, please keep the\nfollowing things in mind before submitting your pull request:\n\n* You compared the existing implementation with the Java API, did you?\n* Please work on the latest possible state of `olivere/elastic`.\n  Use `release-branch.v2` for targeting Elasticsearch 1.x and\n  `release-branch.v3` for targeting 2.x.\n* Create a branch dedicated to your change.\n* If possible, write a test case which confirms your change.\n* Make sure your changes and your tests work with all recent versions of\n  Elasticsearch. We currently support Elasticsearch 1.7.x in the\n  release-branch.v2 and Elasticsearch 2.x in the release-branch.v3.\n* Test your changes before creating a pull request (`go test ./...`).\n* Don't mix several features or bug fixes in one pull request.\n* Create a meaningful commit message.\n* Explain your change, e.g. provide a link to the issue you are fixing and\n  probably a link to the Elasticsearch documentation and/or source code.\n* Format your source with `go fmt`.\n\n## Additional Resources\n\n* [GitHub documentation](https://help.github.com/)\n* [GitHub pull request documentation](https://help.github.com/en/articles/creating-a-pull-request)\n"
  },
  {
    "path": "CONTRIBUTORS",
    "content": "# This is a list of people who have contributed code\n# to the Elastic repository.\n#\n# It is just my small \"thank you\" to all those that helped\n# making Elastic what it is.\n#\n# Please keep this list sorted.\n\n0x6875790d0a [@huydx](https://github.com/huydx)\nAaron Tami [@aarontami](https://github.com/aarontami)\nAdam Alix [@adamalix](https://github.com/adamalix)\nAdam Weiner [@adamweiner](https://github.com/adamweiner)\nAdam Szaraniec [@mimol91](https://github.com/mimol91)\nAdrian Lungu [@AdrianLungu](https://github.com/AdrianLungu)\nalehano [@alehano](https://github.com/alehano)\nAlejandro Carstens [@alejandro-carstens](https://github.com/alejandro-carstens)\nAlex [@akotlar](https://github.com/akotlar)\nAlexander Sack [@asac](https://github.com/asac)\nAlexandre Olivier [@aliphen](https://github.com/aliphen)\nAlexey Sharov [@nizsheanez](https://github.com/nizsheanez)\nAman Jain [@amanjain97](https://github.com/amanjain97)\nAnders [@ANerd](https://github.com/ANerd)\nAndreKR [@AndreKR](https://github.com/AndreKR)\nAndré Bierlein [@ligustah](https://github.com/ligustah)\nAndrew Dunham [@andrew-d](https://github.com/andrew-d)\nAndrew Gaul [@andrewgaul](https://github.com/andrewgaul)\nAndy Walker [@alaska](https://github.com/alaska)\nArpit Agarwal [@arpiagar](https://github.com/arpiagar)\nArquivei [@arquivei](https://github.com/arquivei)\nArtemiy Elozhenko [@artezh](https://github.com/artezh)\narthurgustin [@arthurgustin](https://github.com/arthurgustin)\nBas van Dijk [@basvandijk](https://github.com/basvandijk)\nBenjamin Fernandes [@LotharSee](https://github.com/LotharSee)\nBenjamin Zarzycki [@kf6nux](https://github.com/kf6nux)\nbestgopher [@bestgopher](https://github.com/bestgopher)\nBjörn Gerdau [@kernle32dll](https://github.com/kernle32dll)\nBoris Popovschi [@Zyqsempai](https://github.com/Zyqsempai)\nBowei Xu [@vancexu](https://github.com/vancexu)\nBraden Bassingthwaite [@bbassingthwaite-va](https://github.com/bbassingthwaite-va)\nBrady Love [@bradylove](https://github.com/bradylove)\nBryan Conklin [@bmconklin](https://github.com/bmconklin)\nBruce Zhou [@brucez-isell](https://github.com/brucez-isell)\nCarl Dunham [@carldunham](https://github.com/carldunham)\nCarl Johan Gustavsson [@cjgu](https://github.com/cjgu)\nCarson [@carson0321](https://github.com/carson0321)\nCat [@cat-turner](https://github.com/cat-turner)\nCésar Jiménez [@cesarjimenez](https://github.com/cesarjimenez)\ncforbes [@cforbes](https://github.com/cforbes)\n張泰瑋(Chang Tai Wei) [@david30907d](https://github.com/david30907d)\ncheshire [@NikitaSerenko](https://github.com/NikitaSerenko)\nChris M [@tebriel](https://github.com/tebriel)\nChris Rice [@donutmonger](https://github.com/donutmonger)\nClaudiu Olteanu [@claudiuolteanu](https://github.com/claudiuolteanu)\nChris Duncan [@veqryn](https://github.com/veqryn)\nChris Ludden [@cludden](https://github.com/cludden)\nChristophe Courtaut [@kri5](https://github.com/kri5)\ncmitchell [@cmitchell](https://github.com/cmitchell)\nConnor Peet [@connor4312](https://github.com/connor4312)\nConrad Pankoff [@deoxxa](https://github.com/deoxxa)\nCorey Scott [@corsc](https://github.com/corsc)\nChris Petersen [@ex-nerd](https://github.com/ex-nerd)\nczxichen [@czxichen](https://github.com/czxichen)\nDaniel Barrett [@shendaras](https://github.com/shendaras)\nDaniel Heckrath [@DanielHeckrath](https://github.com/DanielHeckrath)\nDaniel Imfeld [@dimfeld](https://github.com/dimfeld)\nDaniel Santos [@danlsgiga](https://github.com/danlsgiga)\nDavid Emanuel Buchmann [@wuurrd](https://github.com/wuurrd)\nDevin Christensen [@quixoten](https://github.com/quixoten)\ndiacone [@diacone](https://github.com/diacone)\nDiego Becciolini [@itizir](https://github.com/itizir)\nDon Smith III [@cactauz](https://github.com/cactauz)\nDwayne Schultz [@myshkin5](https://github.com/myshkin5)\nElizabeth Jarrett [@mejarrett](https://github.com/mejarrett)\nElliot Williams [@elliotwms](https://github.com/elliotwms)\nEllison Leão [@ellisonleao](https://github.com/ellisonleao)\nEmil Gedda [@EmilGedda](https://github.com/EmilGedda)\nErik Grinaker [@erikgrinaker](https://github.com/erikgrinaker)\nErwin [@eticzon](https://github.com/eticzon)\nEtienne Lafarge [@elafarge](https://github.com/elafarge)\nEugene Egorov [@EugeneEgorov](https://github.com/EugeneEgorov)\nEvan Shaw [@edsrzf](https://github.com/edsrzf)\nFanfan [@wenpos](https://github.com/wenpos)\nFaolan C-P [@fcheslack](https://github.com/fcheslack)\nFilip Tepper [@filiptepper](https://github.com/filiptepper)\nGarrett Kelley [@GarrettKelley](https://github.com/GarrettKelley)\nGaspard Douady [@plopik](https://github.com/plopik)\nGaylord Aulke [@blafasel42](https://github.com/blafasel42)\nGerhard Häring [@ghaering](https://github.com/ghaering)\ngregoryfranklin [@gregoryfranklin](https://github.com/gregoryfranklin)\nGuilherme Silveira [@guilherme-santos](https://github.com/guilherme-santos)\nGuillaume J. Charmes [@creack](https://github.com/creack)\nGuiseppe [@gm42](https://github.com/gm42)\nHan Yu [@MoonighT](https://github.com/MoonighT)\nHarmen [@alicebob](https://github.com/alicebob)\nHaroldo Vélez [@Haroldov](https://github.com/Haroldov)\nHarrison Wright [@wright8191](https://github.com/wright8191)\nHenry Clifford [@hcliff](https://github.com/hcliff)\nHenry Stern [@hstern](https://github.com/hstern)\nHerbert Lu [@lryong](https://github.com/lryong)\nIgor Dubinskiy [@idubinskiy](https://github.com/idubinskiy)\ninitialcontext [@initialcontext](https://github.com/initialcontext)\nIsaac Saldana [@isaldana](https://github.com/isaldana)\nIshan Jain [@ishanjain28](https://github.com/ishanjain28)\nJ Barkey Wolf [@jjhbw](https://github.com/jjhbw)\nJack Lindamood [@cep21](https://github.com/cep21)\nJacob [@jdelgad](https://github.com/jdelgad)\nJan Düpmeier [@jduepmeier](https://github.com/jduepmeier)\nJayme Rotsaert [@jrots](https://github.com/jrots)\nJean-Alexandre Beaumont [@Enteris](https://github.com/Enteris)\nJean-François Roche [@jfroche](https://github.com/jfroche)\nJeff Rand [@jeffrand](https://github.com/jeffrand)\nJeremy Canady [@jrmycanady](https://github.com/jrmycanady)\nJérémie Vexiau [@texvex](https://github.com/texvex)\nJesper Bränn [@Yopi](https://github.com/Yopi)\nJim Berlage [@jimberlage](https://github.com/jimberlage)\nJoe Buck [@four2five](https://github.com/four2five)\nJohn Barker [@j16r](https://github.com/j16r)\nJohn Goodall [@jgoodall](https://github.com/jgoodall)\nJohn Stanford [@jxstanford](https://github.com/jxstanford)\nJonas Groenaas Drange [@semafor](https://github.com/semafor)\nJosef Fröhle [@Dexus](https://github.com/Dexus)\nJosé Martínez [@xose](https://github.com/xose)\nJosh Chorlton [@jchorl](https://github.com/jchorl)\nJpnock [@Jpnock](https://github.com/Jpnock)\njun [@coseyo](https://github.com/coseyo)\nJunpei Tsuji [@jun06t](https://github.com/jun06t)\nKaren Yang [@kyangtt](https://github.com/kyangtt)\nkartlee [@kartlee](https://github.com/kartlee)\nKeith Hatton [@khatton-ft](https://github.com/khatton-ft)\nkel [@liketic](https://github.com/liketic)\nKenta SUZUKI [@suzuken](https://github.com/suzuken)\nKevin Mulvey [@kmulvey](https://github.com/kmulvey)\nKyle Brandt [@kylebrandt](https://github.com/kylebrandt)\nLarry Cinnabar [@larrycinnabar](https://github.com/larrycinnabar)\nLeandro Piccilli [@lpic10](https://github.com/lpic10)\nLee [@leezhm](https://github.com/leezhm)\nlechnertech [@lechnertech](https://github.com/lechnertech)\nM. Zulfa Achsani [@misterciput](https://github.com/misterciput)\nMaciej Lisiewski [@c2h5oh](https://github.com/c2h5oh)\nMara Kim [@autochthe](https://github.com/autochthe)\nMarcy Buccellato [@marcybuccellato](https://github.com/marcybuccellato)\nMark Costello [@mcos](https://github.com/mcos)\nMartin Häger [@protomouse](https://github.com/protomouse)\nMatt Braymer-Hayes [@mattayes](https://github.com/mattayes)\nMedhi Bechina [@mdzor](https://github.com/mdzor)\nMike Beshai [@mbesh](https://github.com/mbesh)\nMikhail Balabin [@mablabin](https://github.com/mbalabin)\nmmfrb [@mmfrb](https://github.com/mmfrb)\nmnpritula [@mnpritula](https://github.com/mnpritula)\nmosa [@mosasiru](https://github.com/mosasiru)\nMuhammet Çakır [@cakirmuha](https://github.com/cakirmuha)\nMunkyu Im [@munkyu](https://github.com/munkyu)\nnaimulhaider [@naimulhaider](https://github.com/naimulhaider)\nNaoya Yoshizawa [@azihsoyn](https://github.com/azihsoyn)\nNaoya Tsutsumi [@tutuming](https://github.com/tutuming)\nNathan Macnamara [@nathanmac](https://github.com/nathanmac)\nNathan Lacey [@nlacey](https://github.com/nlacey)\nnavins [@ishare](https://github.com/ishare)\nNeoCN [@NeoCN](https://github.com/NeoCN)\nNguyen Xuan Dung [@dungnx](https://github.com/dungnx)\nNicholas Wolff [@nwolff](https://github.com/nwolff)\nNick K [@utrack](https://github.com/utrack)\nNick Whyte [@nickw444](https://github.com/nickw444)\nNicolae Vartolomei [@nvartolomei](https://github.com/nvartolomei)\nokhowang [@okhowang](https://github.com/okhowang)\nOrne Brocaar [@brocaar](https://github.com/brocaar)\nottramst [@ottramst](https://github.com/ottramst)\nPaul [@eyeamera](https://github.com/eyeamera)\nPaul Oldenburg [@lr-paul](https://github.com/lr-paul)\nPedro [@otherview](https://github.com/otherview)\nPete C [@peteclark-ft](https://github.com/peteclark-ft)\nPeter Nagy [@nagypeterjob](https://github.com/nagypeterjob)\nPaolo [@ppiccolo](https://github.com/ppiccolo)\nPhillip Baker [@phillbaker](https://github.com/phillbaker)\nQilingZhao [@qilingzhao](https://github.com/qilingzhao)\nIgor Panychek [@panychek](https://github.com/panychek)\nRadoslaw Wesolowski [@r--w](https://github.com/r--w)\nRafał Gałus [@rgalus](https://github.com/rgalus)\nrchicoli [@rchicoli](https://github.com/rchicoli)\nRoman Colohanin [@zuzmic](https://github.com/zuzmic)\nRyan Schmukler [@rschmukler](https://github.com/rschmukler)\nRyan Wynn [@rwynn](https://github.com/rwynn)\nSacheendra talluri [@sacheendra](https://github.com/sacheendra)\nSean DuBois [@Sean-Der](https://github.com/Sean-Der)\nSagan Yaroslav [@sgnrslv](https://github.com/sgnrslv)\nShalin LK [@shalinlk](https://github.com/shalinlk)\nSimon Schneider [@raynigon](https://github.com/raynigon)\nsingham [@zhaochenxiao90](https://github.com/zhaochenxiao90)\nSlawomir CALUCH [@slawo](https://github.com/slawo)\nsoarpenguin [@soarpenguin](https://github.com/soarpenguin)\nStephan Krynauw [@skrynauw](https://github.com/skrynauw)\nStephen Kubovic [@stephenkubovic](https://github.com/stephenkubovic)\nStuart Warren [@Woz](https://github.com/stuart-warren)\nSulaiman [@salajlan](https://github.com/salajlan)\nSundar [@sundarv85](https://github.com/sundarv85)\nSwarlston [@Swarlston](https://github.com/Swarlston)\nTake [ww24](https://github.com/ww24)\nTetsuya Morimoto [@t2y](https://github.com/t2y)\nTheZeroSlave [@TheZeroSlave](https://github.com/TheZeroSlave)\nTomasz Elendt [@telendt](https://github.com/telendt)\nTimeEmit [@TimeEmit](https://github.com/timeemit)\nTusharM [@tusharm](https://github.com/tusharm)\nwangtuo [@wangtuo](https://github.com/wangtuo)\nWédney Yuri [@wedneyyuri](https://github.com/wedneyyuri)\nWesley Kim [@wesleyk](https://github.com/wesleyk)\nwolfkdy [@wolfkdy](https://github.com/wolfkdy)\nWyndham Blanton [@wyndhblb](https://github.com/wyndhblb)\nYarden Bar [@ayashjorden](https://github.com/ayashjorden)\nYuya Kusakabe [@higebu](https://github.com/higebu)\nzakthomas [@zakthomas](https://github.com/zakthomas)\nZach [@snowzach](https://github.com/snowzach)\nzhangxin [@visaxin](https://github.com/visaxin)\n@林 [@zplzpl](https://github.com/zplzpl)\n"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "content": "Please use the following questions as a guideline to help me answer\nyour issue/question without further inquiry. Thank you.\n\n### Which version of Elastic are you using?\n\n[ ] elastic.v7 (for Elasticsearch 7.x)\n[ ] elastic.v6 (for Elasticsearch 6.x)\n[ ] elastic.v5 (for Elasticsearch 5.x)\n[ ] elastic.v3 (for Elasticsearch 2.x)\n[ ] elastic.v2 (for Elasticsearch 1.x)\n\n### Please describe the expected behavior\n\n\n### Please describe the actual behavior\n\n\n### Any steps to reproduce the behavior?\n\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\nCopyright © 2012-2015 Oliver Eilhard\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the “Software”), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": ".PHONY: test\ntest:\n\tgo test -race -deprecations -strict-decoder -v . ./aws/... ./config/... ./trace/... ./uritemplates/...\n"
  },
  {
    "path": "README.md",
    "content": "# Elastic\n\n**This is a development branch that is actively being worked on. DO NOT USE IN PRODUCTION! If you want to use stable versions of Elastic, please use Go modules for the 7.x release (or later) or a dependency manager like [dep](https://github.com/golang/dep) for earlier releases.**\n\nElastic is an [Elasticsearch](http://www.elasticsearch.org/) client for the\n[Go](http://www.golang.org/) programming language.\n\n[![Build Status](https://github.com/olivere/elastic/workflows/Test/badge.svg)](https://github.com/olivere/elastic/actions)\n[![Godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://pkg.go.dev/github.com/olivere/elastic/v7?tab=doc)\n[![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/olivere/elastic/master/LICENSE)\n\nSee the [wiki](https://github.com/olivere/elastic/wiki) for additional information about Elastic.\n\n<a href=\"https://www.buymeacoffee.com/Bjd96U8fm\" target=\"_blank\"><img src=\"https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png\" alt=\"Buy Me A Coffee\" style=\"height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;\" ></a>\n\n## Releases\n\n**The release branches (e.g. [`release-branch.v7`](https://github.com/olivere/elastic/tree/release-branch.v7))\nare actively being worked on and can break at any time.\nIf you want to use stable versions of Elastic, please use Go modules.**\n\nHere's the version matrix:\n\nElasticsearch version | Elastic version  | Package URL | Remarks |\n----------------------|------------------|-------------|---------|\n7.x                   | 7.0              | [`github.com/olivere/elastic/v7`](https://github.com/olivere/elastic) ([source](https://github.com/olivere/elastic/tree/release-branch.v7) [doc](http://godoc.org/github.com/olivere/elastic)) | Use Go modules.\n6.x                   | 6.0              | [`github.com/olivere/elastic`](https://github.com/olivere/elastic) ([source](https://github.com/olivere/elastic/tree/release-branch.v6) [doc](http://godoc.org/github.com/olivere/elastic)) | Use a dependency manager (see below).\n5.x                   | 5.0              | [`gopkg.in/olivere/elastic.v5`](https://gopkg.in/olivere/elastic.v5) ([source](https://github.com/olivere/elastic/tree/release-branch.v5) [doc](http://godoc.org/gopkg.in/olivere/elastic.v5)) | Actively maintained.\n2.x                   | 3.0              | [`gopkg.in/olivere/elastic.v3`](https://gopkg.in/olivere/elastic.v3) ([source](https://github.com/olivere/elastic/tree/release-branch.v3) [doc](http://godoc.org/gopkg.in/olivere/elastic.v3)) | Deprecated. Please update.\n1.x                   | 2.0              | [`gopkg.in/olivere/elastic.v2`](https://gopkg.in/olivere/elastic.v2) ([source](https://github.com/olivere/elastic/tree/release-branch.v2) [doc](http://godoc.org/gopkg.in/olivere/elastic.v2)) | Deprecated. Please update.\n0.9-1.3               | 1.0              | [`gopkg.in/olivere/elastic.v1`](https://gopkg.in/olivere/elastic.v1) ([source](https://github.com/olivere/elastic/tree/release-branch.v1) [doc](http://godoc.org/gopkg.in/olivere/elastic.v1)) | Deprecated. Please update.\n\n**Example:**\n\nYou have installed Elasticsearch 7.0.0 and want to use Elastic.\nAs listed above, you should use Elastic 7.0 (code is in `release-branch.v7`).\n\nTo use the required version of Elastic in your application, you\nshould use [Go modules](https://github.com/golang/go/wiki/Modules)\nto manage dependencies. Make sure to use a version such as `7.0.0` or later.\n\nTo use Elastic, import:\n\n```go\nimport \"github.com/olivere/elastic/v7\"\n```\n\n### Elastic 7.0\n\nElastic 7.0 targets Elasticsearch 7.x which [was released on April 10th 2019](https://www.elastic.co/guide/en/elasticsearch/reference/7.0/release-notes-7.0.0.html).\n\nAs always with major version, there are a lot of [breaking changes](https://www.elastic.co/guide/en/elasticsearch/reference/7.0/release-notes-7.0.0.html#breaking-7.0.0).\nWe will use this as an opportunity to [clean up and refactor Elastic](https://github.com/olivere/elastic/blob/release-branch.v7/CHANGELOG-7.0.md),\nas we already did in earlier (major) releases.\n\n### Elastic 6.0\n\nElastic 6.0 targets Elasticsearch 6.x which was [released on 14th November 2017](https://www.elastic.co/blog/elasticsearch-6-0-0-released).\n\nNotice that there are a lot of [breaking changes in Elasticsearch 6.0](https://www.elastic.co/guide/en/elasticsearch/reference/6.7/breaking-changes-6.0.html)\nand we used this as an opportunity to [clean up and refactor Elastic](https://github.com/olivere/elastic/blob/release-branch.v6/CHANGELOG-6.0.md)\nas we did in the transition from earlier versions of Elastic.\n\n### Elastic 5.0\n\nElastic 5.0 targets Elasticsearch 5.0.0 and later. Elasticsearch 5.0.0 was\n[released on 26th October 2016](https://www.elastic.co/blog/elasticsearch-5-0-0-released).\n\nNotice that there are will be a lot of [breaking changes in Elasticsearch 5.0](https://www.elastic.co/guide/en/elasticsearch/reference/5.0/breaking-changes-5.0.html)\nand we used this as an opportunity to [clean up and refactor Elastic](https://github.com/olivere/elastic/blob/release-branch.v5/CHANGELOG-5.0.md)\nas we did in the transition from Elastic 2.0 (for Elasticsearch 1.x) to Elastic 3.0 (for Elasticsearch 2.x).\n\nFurthermore, the jump in version numbers will give us a chance to be in sync with the Elastic Stack.\n\n### Elastic 3.0\n\nElastic 3.0 targets Elasticsearch 2.x and is published via [`gopkg.in/olivere/elastic.v3`](https://gopkg.in/olivere/elastic.v3).\n\nElastic 3.0 will only get critical bug fixes. You should update to a recent version.\n\n### Elastic 2.0\n\nElastic 2.0 targets Elasticsearch 1.x and is published via [`gopkg.in/olivere/elastic.v2`](https://gopkg.in/olivere/elastic.v2).\n\nElastic 2.0 will only get critical bug fixes. You should update to a recent version.\n\n### Elastic 1.0\n\nElastic 1.0 is deprecated. You should really update Elasticsearch and Elastic\nto a recent version.\n\nHowever, if you cannot update for some reason, don't worry. Version 1.0 is\nstill available. All you need to do is go-get it and change your import path\nas described above.\n\n\n## Status\n\nWe use Elastic in production since 2012. Elastic is stable but the API changes\nnow and then. We strive for API compatibility.\nHowever, Elasticsearch sometimes introduces [breaking changes](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes.html)\nand we sometimes have to adapt.\n\nHaving said that, there have been no big API changes that required you\nto rewrite your application big time. More often than not it's renaming APIs\nand adding/removing features so that Elastic is in sync with Elasticsearch.\n\nElastic has been used in production starting with Elasticsearch 0.90 up to recent 7.x\nversions.\nWe recently switched to [GitHub Actions for testing](https://github.com/olivere/elastic/actions).\nBefore that, we used [Travis CI](https://travis-ci.org/olivere/elastic) successfully for years).\n\nElasticsearch has quite a few features. Most of them are implemented\nby Elastic. I add features and APIs as required. It's straightforward\nto implement missing pieces. I'm accepting pull requests :-)\n\nHaving said that, I hope you find the project useful.\n\n\n## Getting Started\n\nThe first thing you do is to create a [Client](https://github.com/olivere/elastic/blob/master/client.go).\nThe client connects to Elasticsearch on `http://127.0.0.1:9200` by default.\n\nYou typically create one client for your app. Here's a complete example of\ncreating a client, creating an index, adding a document, executing a search etc.\n\nAn example is available [here](https://olivere.github.io/elastic/).\n\nHere's a [link to a complete working example for v6](https://gist.github.com/olivere/e4a376b4783c0914e44ea4f745ce2ebf).\n\nHere are a few tips on how to get used to Elastic:\n\n1. Head over to the [Wiki](https://github.com/olivere/elastic/wiki) for detailed information and\n   topics like e.g. [how to add a middleware](https://github.com/olivere/elastic/wiki/HttpTransport)\n   or how to [connect to AWS](https://github.com/olivere/elastic/wiki/Using-with-AWS-Elasticsearch-Service).\n2. If you are unsure how to implement something, read the tests (all `_test.go` files).\n   They not only serve as a guard against changes, but also as a reference.\n3. The [recipes](https://github.com/olivere/elastic/tree/release-branch.v6/recipes)\n   contains small examples on how to implement something, e.g. bulk indexing, scrolling etc.\n\n\n## API Status\n\n### Document APIs\n\n- [x] Index API\n- [x] Get API\n- [x] Delete API\n- [x] Delete By Query API\n- [x] Update API\n- [x] Update By Query API\n- [x] Multi Get API\n- [x] Bulk API\n- [x] Reindex API\n- [x] Term Vectors\n- [x] Multi termvectors API\n\n### Search APIs\n\n- [x] Search\n- [x] Search Template\n- [ ] Multi Search Template\n- [x] Search Shards API\n- [x] Suggesters\n  - [x] Term Suggester\n  - [x] Phrase Suggester\n  - [x] Completion Suggester\n  - [x] Context Suggester\n- [x] Multi Search API\n- [x] Count API\n- [x] Validate API\n- [x] Explain API\n- [x] Profile API\n- [x] Field Capabilities API\n\n### Aggregations\n\n- Metrics Aggregations\n  - [x] Avg\n  - [ ] Boxplot (X-pack)\n  - [x] Cardinality\n  - [x] Extended Stats\n  - [x] Geo Bounds\n  - [x] Geo Centroid\n  - [x] Matrix stats\n  - [x] Max\n  - [x] Median absolute deviation\n  - [x] Min\n  - [x] Percentile Ranks\n  - [x] Percentiles\n  - [ ] Rate (X-pack)\n  - [ ] Scripted Metric\n  - [x] Stats\n  - [ ] String stats (X-pack)\n  - [x] Sum\n  - [ ] T-test (X-pack)\n  - [x] Top Hits\n  - [x] Top metrics (X-pack)\n  - [x] Value Count\n  - [x] Weighted avg\n- Bucket Aggregations\n  - [x] Adjacency Matrix\n  - [x] Auto-interval Date Histogram\n  - [x] Children\n  - [x] Composite\n  - [x] Date Histogram\n  - [x] Date Range\n  - [x] Diversified Sampler\n  - [x] Filter\n  - [x] Filters\n  - [x] Geo Distance\n  - [x] Geohash Grid\n  - [x] Geotile grid\n  - [x] Global\n  - [x] Histogram\n  - [x] IP Range\n  - [x] Missing\n  - [x] Nested\n  - [ ] Parent\n  - [x] Range\n  - [ ] Rare terms\n  - [x] Reverse Nested\n  - [x] Sampler\n  - [x] Significant Terms\n  - [x] Significant Text\n  - [x] Terms\n  - [ ] Variable width histogram\n- Pipeline Aggregations\n  - [x] Avg Bucket\n  - [x] Bucket Script\n  - [x] Bucket Selector\n  - [x] Bucket Sort\n  - [ ] Cumulative cardinality (X-pack)\n  - [x] Cumulative Sum\n  - [x] Derivative\n  - [ ] Extended Stats Bucket\n  - [ ] Inference bucket (X-pack)\n  - [x] Max Bucket\n  - [x] Min Bucket\n  - [x] Moving Average\n  - [x] Moving function\n  - [ ] Moving percentiles (X-pack)\n  - [ ] Normalize (X-pack)\n  - [x] Percentiles Bucket\n  - [x] Serial Differencing\n  - [x] Stats Bucket\n  - [x] Sum Bucket\n- [x] Aggregation Metadata\n\n### Indices APIs\n\n- [x] Create Index\n- [x] Delete Index\n- [x] Get Index\n- [x] Indices Exists\n- [x] Open / Close Index\n- [x] Shrink Index\n- [x] Rollover Index\n- [x] Put Mapping\n- [x] Get Mapping\n- [x] Get Field Mapping\n- [x] Types Exists\n- [x] Index Aliases\n- [x] Update Indices Settings\n- [x] Get Settings\n- [x] Analyze\n  - [x] Explain Analyze\n- [x] Index Templates\n- [x] Indices Stats\n- [x] Indices Segments\n- [ ] Indices Recovery\n- [ ] Indices Shard Stores\n- [x] Clear Cache\n- [x] Flush\n  - [x] Synced Flush\n- [x] Refresh\n- [x] Force Merge\n\n### Index Lifecycle Management APIs\n\n- [x] Create Policy\n- [x] Get Policy\n- [x] Delete Policy\n- [ ] Move to Step\n- [ ] Remove Policy\n- [ ] Retry Policy\n- [ ] Get Ilm Status\n- [ ] Explain Lifecycle\n- [ ] Start Ilm\n- [ ] Stop Ilm\n\n### cat APIs\n\n- [X] cat aliases\n- [X] cat allocation\n- [X] cat count\n- [X] cat fielddata\n- [X] cat health\n- [X] cat indices\n- [x] cat master\n- [ ] cat nodeattrs\n- [ ] cat nodes\n- [ ] cat pending tasks\n- [ ] cat plugins\n- [ ] cat recovery\n- [ ] cat repositories\n- [ ] cat thread pool\n- [ ] cat shards\n- [ ] cat segments\n- [X] cat snapshots\n- [ ] cat templates\n\n### Cluster APIs\n\n- [x] Cluster Health\n- [x] Cluster State\n- [x] Cluster Stats\n- [ ] Pending Cluster Tasks\n- [x] Cluster Reroute\n- [ ] Cluster Update Settings\n- [x] Nodes Stats\n- [x] Nodes Info\n- [ ] Nodes Feature Usage\n- [ ] Remote Cluster Info\n- [x] Task Management API\n- [ ] Nodes hot_threads\n- [ ] Cluster Allocation Explain API\n\n### Rollup APIs (XPack)\n- [x] Create Job\n- [x] Delete Job\n- [x] Get Job\n- [x] Start Job\n- [x] Stop Job\n\n### Query DSL\n\n- [x] Match All Query\n- [x] Inner hits\n- Full text queries\n  - [x] Match Query\n  - [x] Match Boolean Prefix Query\n  - [x] Match Phrase Query\n  - [x] Match Phrase Prefix Query\n  - [x] Multi Match Query\n  - [x] Common Terms Query\n  - [x] Query String Query\n  - [x] Simple Query String Query\n  - [x] Combined Fields Query\n  - [x] Intervals Query\n- Term level queries\n  - [x] Term Query\n  - [x] Terms Query\n  - [x] Terms Set Query\n  - [x] Range Query\n  - [x] Exists Query\n  - [x] Prefix Query\n  - [x] Wildcard Query\n  - [x] Regexp Query\n  - [x] Fuzzy Query\n  - [x] Type Query\n  - [x] Ids Query\n- Compound queries\n  - [x] Constant Score Query\n  - [x] Bool Query\n  - [x] Dis Max Query\n  - [x] Function Score Query\n  - [x] Boosting Query\n- Joining queries\n  - [x] Nested Query\n  - [x] Has Child Query\n  - [x] Has Parent Query\n  - [x] Parent Id Query\n- Geo queries\n  - [ ] GeoShape Query\n  - [x] Geo Bounding Box Query\n  - [x] Geo Distance Query\n  - [x] Geo Polygon Query\n- Specialized queries\n  - [x] Distance Feature Query\n  - [x] More Like This Query\n  - [x] Script Query\n  - [x] Script Score Query\n  - [x] Percolate Query\n- Span queries\n  - [x] Span Term Query\n  - [ ] Span Multi Term Query\n  - [x] Span First Query\n  - [x] Span Near Query\n  - [ ] Span Or Query\n  - [ ] Span Not Query\n  - [ ] Span Containing Query\n  - [ ] Span Within Query\n  - [ ] Span Field Masking Query\n- [ ] Minimum Should Match\n- [ ] Multi Term Query Rewrite\n\n### Modules\n\n- Snapshot and Restore\n  - [x] Repositories\n  - [x] Snapshot get\n  - [x] Snapshot create\n  - [x] Snapshot delete\n  - [ ] Restore\n  - [ ] Snapshot status\n  - [ ] Monitoring snapshot/restore status\n  - [ ] Stopping currently running snapshot and restore\n- Scripting\n  - [x] GetScript\n  - [x] PutScript\n  - [x] DeleteScript\n\n### Sorting\n\n- [x] Sort by score\n- [x] Sort by field\n- [x] Sort by geo distance\n- [x] Sort by script\n- [x] Sort by doc\n\n### Scrolling\n\nScrolling is supported via a  `ScrollService`. It supports an iterator-like interface.\nThe `ClearScroll` API is implemented as well.\n\nA pattern for [efficiently scrolling in parallel](https://github.com/olivere/elastic/wiki/ScrollParallel)\nis described in the [Wiki](https://github.com/olivere/elastic/wiki).\n\n## How to contribute\n\nRead [the contribution guidelines](https://github.com/olivere/elastic/blob/master/CONTRIBUTING.md).\n\n## Credits\n\nThanks a lot for the great folks working hard on\n[Elasticsearch](https://www.elastic.co/products/elasticsearch)\nand\n[Go](https://golang.org/).\n\nElastic uses portions of the\n[uritemplates](https://github.com/jtacoma/uritemplates) library\nby Joshua Tacoma,\n[backoff](https://github.com/cenkalti/backoff) by Cenk Altı and\n[leaktest](https://github.com/fortytw2/leaktest) by Ian Chiles.\n\n## LICENSE\n\nMIT-LICENSE. See [LICENSE](http://olivere.mit-license.org/)\nor the LICENSE file provided in the repository for details.\n"
  },
  {
    "path": "acknowledged_response.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// AcknowledgedResponse is returned from various APIs. It simply indicates\n// whether the operation is acknowledged or not.\ntype AcknowledgedResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "aws/sign_v4.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage aws\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/smartystreets/go-aws-auth\"\n)\n\n// NewV4SigningClient returns an *http.Client that will sign all requests with AWS V4 Signing.\nfunc NewV4SigningClient(credentials awsauth.Credentials) *http.Client {\n\treturn NewV4SigningClientWithHTTPClient(credentials, http.DefaultClient)\n}\n\n// NewV4SigningClientWithHTTPClient returns an *http.Client that will sign all requests with AWS V4 Signing.\nfunc NewV4SigningClientWithHTTPClient(credentials awsauth.Credentials, httpClient *http.Client) *http.Client {\n\treturn &http.Client{\n\t\tTransport: V4Transport{\n\t\t\tHTTPClient:  httpClient,\n\t\t\tCredentials: credentials,\n\t\t},\n\t}\n}\n\n// V4Transport is a RoundTripper that will sign requests with AWS V4 Signing\ntype V4Transport struct {\n\tHTTPClient  *http.Client\n\tCredentials awsauth.Credentials\n}\n\n// RoundTrip uses the underlying RoundTripper transport, but signs request first with AWS V4 Signing\nfunc (st V4Transport) RoundTrip(req *http.Request) (*http.Response, error) {\n\t// Instead of directly modifying the request then calling http.DefaultTransport,\n\t// instead restart the request with the HTTPClient.Do function,\n\t// because the HTTPClient includes safeguards around not forwarding the\n\t// signed Authorization header to untrusted domains.\n\treturn st.HTTPClient.Do(awsauth.Sign4(req, st.Credentials))\n}\n"
  },
  {
    "path": "aws/sign_v4_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage aws\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\n\tawsauth \"github.com/smartystreets/go-aws-auth\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc TestSigningClient(t *testing.T) {\n\tvar req *http.Request\n\tts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tswitch r.URL.Path {\n\t\tcase \"/\":\n\t\t\treq = r // capture the HTTP request\n\t\t\tw.WriteHeader(http.StatusOK)\n\t\t\tfmt.Fprintln(w, `{\n\t\t\t\t\"name\" : \"Qg28M36\",\n\t\t\t\t\"cluster_name\" : \"docker-cluster\",\n\t\t\t\t\"cluster_uuid\" : \"rwHa7BBnRC2h8KoDfCbmuQ\",\n\t\t\t\t\"version\" : {\n\t\t\t\t\t\"number\" : \"6.3.2\",\n\t\t\t\t\t\"build_flavor\" : \"oss\",\n\t\t\t\t\t\"build_type\" : \"tar\",\n\t\t\t\t\t\"build_hash\" : \"053779d\",\n\t\t\t\t\t\"build_date\" : \"2018-07-20T05:20:23.451332Z\",\n\t\t\t\t\t\"build_snapshot\" : false,\n\t\t\t\t\t\"lucene_version\" : \"7.3.1\",\n\t\t\t\t\t\"minimum_wire_compatibility_version\" : \"5.6.0\",\n\t\t\t\t\t\"minimum_index_compatibility_version\" : \"5.0.0\"\n\t\t\t\t},\n\t\t\t\t\"tagline\" : \"You Know, for Search\"\n\t\t\t}`)\n\t\t\treturn\n\t\tdefault:\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t}))\n\tdefer ts.Close()\n\n\tcred := awsauth.Credentials{\n\t\tAccessKeyID:     \"dev\",\n\t\tSecretAccessKey: \"secret\",\n\t}\n\tsigningClient := NewV4SigningClient(cred)\n\n\t// Create a simple Ping request via Elastic\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(ts.URL),\n\t\telastic.SetHttpClient(signingClient),\n\t\telastic.SetHealthcheck(false),\n\t\telastic.SetSniff(false),\n\t)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, code, err := client.Ping(ts.URL).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := http.StatusOK, code; want != have {\n\t\tt.Fatalf(\"want Status=%d, have %d\", want, have)\n\t}\n\tif want, have := \"You Know, for Search\", res.TagLine; want != have {\n\t\tt.Fatalf(\"want TagLine=%q, have %q\", want, have)\n\t}\n\n\t// Check the request recorded in the HTTP test server (see above)\n\tif req == nil {\n\t\tt.Fatal(\"expected to capture HTTP request\")\n\t}\n\tif have := req.Header.Get(\"Authorization\"); have == \"\" {\n\t\tt.Fatal(\"expected Authorization header\")\n\t}\n\tif have := req.Header.Get(\"X-Amz-Date\"); have == \"\" {\n\t\tt.Fatal(\"expected X-Amz-Date header\")\n\t}\n\tif want, have := `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`, req.Header.Get(\"X-Amz-Content-Sha256\"); want != have {\n\t\tt.Fatalf(\"want header of X-Amz-Content-Sha256=%q, have %q\", want, have)\n\t}\n}\n"
  },
  {
    "path": "aws/v4/CREDITS",
    "content": "This package contains code that is Copyright (c) 2016 Anthony Atkinson\nand licensed under the MIT license.\n\nSee https://github.com/sha1sum/aws_signing_client.\n"
  },
  {
    "path": "aws/v4/aws_v4.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage v4\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/aws/aws-sdk-go/aws/credentials\"\n\tv4 \"github.com/aws/aws-sdk-go/aws/signer/v4\"\n)\n\n// NewV4SigningClient returns an *http.Client that will sign all requests with AWS V4 Signing.\nfunc NewV4SigningClient(creds *credentials.Credentials, region string) *http.Client {\n\treturn NewV4SigningClientWithHTTPClient(creds, region, http.DefaultClient)\n}\n\n// NewV4SigningClientWithHTTPClient returns an *http.Client that will sign all requests with AWS V4 Signing.\nfunc NewV4SigningClientWithHTTPClient(creds *credentials.Credentials, region string, httpClient *http.Client) *http.Client {\n\treturn &http.Client{\n\t\tTransport: Transport{\n\t\t\tclient: httpClient,\n\t\t\tcreds:  creds,\n\t\t\tsigner: v4.NewSigner(creds),\n\t\t\tregion: region,\n\t\t},\n\t}\n}\n\n// Transport is a RoundTripper that will sign requests with AWS V4 Signing\ntype Transport struct {\n\tclient *http.Client\n\tcreds  *credentials.Credentials\n\tsigner *v4.Signer\n\tregion string\n}\n\n// RoundTrip uses the underlying RoundTripper transport, but signs request first with AWS V4 Signing\nfunc (st Transport) RoundTrip(req *http.Request) (*http.Response, error) {\n\tif h, ok := req.Header[\"Authorization\"]; ok && len(h) > 0 && strings.HasPrefix(h[0], \"AWS4\") {\n\t\t// Received a signed request, just pass it on.\n\t\treturn st.client.Do(req)\n\t}\n\n\tif strings.Contains(req.URL.RawPath, \"%2C\") {\n\t\t// Escaping path\n\t\treq.URL.RawPath = url.PathEscape(req.URL.RawPath)\n\t}\n\n\tnow := time.Now().UTC()\n\treq.Header.Set(\"Date\", now.Format(time.RFC3339))\n\n\tvar err error\n\tswitch req.Body {\n\tcase nil:\n\t\t_, err = st.signer.Sign(req, nil, \"es\", st.region, now)\n\tdefault:\n\t\tswitch body := req.Body.(type) {\n\t\tcase io.ReadSeeker:\n\t\t\t_, err = st.signer.Sign(req, body, \"es\", st.region, now)\n\t\tdefault:\n\t\t\tbuf, err := ioutil.ReadAll(req.Body)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\treq.Body = ioutil.NopCloser(bytes.NewReader(buf))\n\t\t\t_, err = st.signer.Sign(req, bytes.NewReader(buf), \"es\", st.region, time.Now().UTC())\n\t\t}\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn st.client.Do(req)\n}\n"
  },
  {
    "path": "aws/v4/aws_v4_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage v4\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\n\t\"github.com/aws/aws-sdk-go/aws/credentials\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc TestSigningClient(t *testing.T) {\n\tvar req *http.Request\n\tts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tswitch r.URL.Path {\n\t\tcase \"/\":\n\t\t\treq = r // capture the HTTP request\n\t\t\tw.WriteHeader(http.StatusOK)\n\t\t\tfmt.Fprintln(w, `{\n\t\t\t\t\"name\" : \"Qg28M36\",\n\t\t\t\t\"cluster_name\" : \"docker-cluster\",\n\t\t\t\t\"cluster_uuid\" : \"rwHa7BBnRC2h8KoDfCbmuQ\",\n\t\t\t\t\"version\" : {\n\t\t\t\t\t\"number\" : \"6.3.2\",\n\t\t\t\t\t\"build_flavor\" : \"oss\",\n\t\t\t\t\t\"build_type\" : \"tar\",\n\t\t\t\t\t\"build_hash\" : \"053779d\",\n\t\t\t\t\t\"build_date\" : \"2018-07-20T05:20:23.451332Z\",\n\t\t\t\t\t\"build_snapshot\" : false,\n\t\t\t\t\t\"lucene_version\" : \"7.3.1\",\n\t\t\t\t\t\"minimum_wire_compatibility_version\" : \"5.6.0\",\n\t\t\t\t\t\"minimum_index_compatibility_version\" : \"5.0.0\"\n\t\t\t\t},\n\t\t\t\t\"tagline\" : \"You Know, for Search\"\n\t\t\t}`)\n\t\t\treturn\n\t\tdefault:\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t}))\n\tdefer ts.Close()\n\n\tcred := credentials.NewStaticCredentials(\"dev\", \"secret\", \"\")\n\t// Don't do this in production!\n\tinsecureHttpClient := &http.Client{\n\t\tTransport: &http.Transport{\n\t\t\tTLSClientConfig: &tls.Config{\n\t\t\t\tInsecureSkipVerify: true,\n\t\t\t},\n\t\t},\n\t}\n\tsigningClient := NewV4SigningClientWithHTTPClient(cred, \"us-east-1\", insecureHttpClient)\n\n\t// Create a simple Ping request via Elastic\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(ts.URL),\n\t\telastic.SetHttpClient(signingClient),\n\t\telastic.SetHealthcheck(false),\n\t\telastic.SetSniff(false),\n\t)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, code, err := client.Ping(ts.URL).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := http.StatusOK, code; want != have {\n\t\tt.Fatalf(\"want Status=%d, have %d\", want, have)\n\t}\n\tif want, have := \"You Know, for Search\", res.TagLine; want != have {\n\t\tt.Fatalf(\"want TagLine=%q, have %q\", want, have)\n\t}\n\n\t// Check the request recorded in the HTTP test server (see above)\n\tif req == nil {\n\t\tt.Fatal(\"expected to capture HTTP request\")\n\t}\n\tif have := req.Header.Get(\"Authorization\"); have == \"\" {\n\t\tt.Fatal(\"expected Authorization header\")\n\t}\n\tif have := req.Header.Get(\"X-Amz-Date\"); have == \"\" {\n\t\tt.Fatal(\"expected X-Amz-Date header\")\n\t}\n\t/*\n\t\tif want, have := `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`, req.Header.Get(\"X-Amz-Content-Sha256\"); want != have {\n\t\t\tt.Fatalf(\"want header of X-Amz-Content-Sha256=%q, have %q\", want, have)\n\t\t}\n\t*/\n}\n"
  },
  {
    "path": "backoff.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"math\"\n\t\"math/rand\"\n\t\"sync\"\n\t\"time\"\n)\n\n// BackoffFunc specifies the signature of a function that returns the\n// time to wait before the next call to a resource. To stop retrying\n// return false in the 2nd return value.\ntype BackoffFunc func(retry int) (time.Duration, bool)\n\n// Backoff allows callers to implement their own Backoff strategy.\ntype Backoff interface {\n\t// Next implements a BackoffFunc.\n\tNext(retry int) (time.Duration, bool)\n}\n\n// -- ZeroBackoff --\n\n// ZeroBackoff is a fixed backoff policy whose backoff time is always zero,\n// meaning that the operation is retried immediately without waiting,\n// indefinitely.\ntype ZeroBackoff struct{}\n\n// Next implements BackoffFunc for ZeroBackoff.\nfunc (b ZeroBackoff) Next(retry int) (time.Duration, bool) {\n\treturn 0, true\n}\n\n// -- StopBackoff --\n\n// StopBackoff is a fixed backoff policy that always returns false for\n// Next(), meaning that the operation should never be retried.\ntype StopBackoff struct{}\n\n// Next implements BackoffFunc for StopBackoff.\nfunc (b StopBackoff) Next(retry int) (time.Duration, bool) {\n\treturn 0, false\n}\n\n// -- ConstantBackoff --\n\n// ConstantBackoff is a backoff policy that always returns the same delay.\ntype ConstantBackoff struct {\n\tinterval time.Duration\n}\n\n// NewConstantBackoff returns a new ConstantBackoff.\nfunc NewConstantBackoff(interval time.Duration) *ConstantBackoff {\n\treturn &ConstantBackoff{interval: interval}\n}\n\n// Next implements BackoffFunc for ConstantBackoff.\nfunc (b *ConstantBackoff) Next(retry int) (time.Duration, bool) {\n\treturn b.interval, true\n}\n\n// -- Exponential --\n\n// ExponentialBackoff implements the simple exponential backoff described by\n// Douglas Thain at http://dthain.blogspot.de/2009/02/exponential-backoff-in-distributed.html.\ntype ExponentialBackoff struct {\n\tt float64 // initial timeout (in msec)\n\tf float64 // exponential factor (e.g. 2)\n\tm float64 // maximum timeout (in msec)\n}\n\n// NewExponentialBackoff returns a ExponentialBackoff backoff policy.\n// Use initialTimeout to set the first/minimal interval\n// and maxTimeout to set the maximum wait interval.\nfunc NewExponentialBackoff(initialTimeout, maxTimeout time.Duration) *ExponentialBackoff {\n\treturn &ExponentialBackoff{\n\t\tt: float64(int64(initialTimeout / time.Millisecond)),\n\t\tf: 2.0,\n\t\tm: float64(int64(maxTimeout / time.Millisecond)),\n\t}\n}\n\n// Next implements BackoffFunc for ExponentialBackoff.\nfunc (b *ExponentialBackoff) Next(retry int) (time.Duration, bool) {\n\tr := 1.0 + rand.Float64() // random number in [1..2]\n\tm := math.Min(r*b.t*math.Pow(b.f, float64(retry)), b.m)\n\tif m >= b.m {\n\t\treturn 0, false\n\t}\n\td := time.Duration(int64(m)) * time.Millisecond\n\treturn d, true\n}\n\n// -- Simple Backoff --\n\n// SimpleBackoff takes a list of fixed values for backoff intervals.\n// Each call to Next returns the next value from that fixed list.\n// After each value is returned, subsequent calls to Next will only return\n// the last element. The values are optionally \"jittered\" (off by default).\ntype SimpleBackoff struct {\n\tsync.Mutex\n\tticks  []int\n\tjitter bool\n}\n\n// NewSimpleBackoff creates a SimpleBackoff algorithm with the specified\n// list of fixed intervals in milliseconds.\nfunc NewSimpleBackoff(ticks ...int) *SimpleBackoff {\n\treturn &SimpleBackoff{\n\t\tticks:  ticks,\n\t\tjitter: false,\n\t}\n}\n\n// Jitter enables or disables jittering values.\nfunc (b *SimpleBackoff) Jitter(flag bool) *SimpleBackoff {\n\tb.Lock()\n\tb.jitter = flag\n\tb.Unlock()\n\treturn b\n}\n\n// jitter randomizes the interval to return a value of [0.5*millis .. 1.5*millis].\nfunc jitter(millis int) int {\n\tif millis <= 0 {\n\t\treturn 0\n\t}\n\treturn millis/2 + rand.Intn(millis)\n}\n\n// Next implements BackoffFunc for SimpleBackoff.\nfunc (b *SimpleBackoff) Next(retry int) (time.Duration, bool) {\n\tb.Lock()\n\tdefer b.Unlock()\n\n\tif retry >= len(b.ticks) {\n\t\treturn 0, false\n\t}\n\n\tms := b.ticks[retry]\n\tif b.jitter {\n\t\tms = jitter(ms)\n\t}\n\treturn time.Duration(ms) * time.Millisecond, true\n}\n"
  },
  {
    "path": "backoff_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"math/rand\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestZeroBackoff(t *testing.T) {\n\tb := ZeroBackoff{}\n\t_, ok := b.Next(0)\n\tif !ok {\n\t\tt.Fatalf(\"expected %v, got %v\", true, ok)\n\t}\n}\n\nfunc TestStopBackoff(t *testing.T) {\n\tb := StopBackoff{}\n\t_, ok := b.Next(0)\n\tif ok {\n\t\tt.Fatalf(\"expected %v, got %v\", false, ok)\n\t}\n}\n\nfunc TestConstantBackoff(t *testing.T) {\n\tb := NewConstantBackoff(time.Second)\n\td, ok := b.Next(0)\n\tif !ok {\n\t\tt.Fatalf(\"expected %v, got %v\", true, ok)\n\t}\n\tif d != time.Second {\n\t\tt.Fatalf(\"expected %v, got %v\", time.Second, d)\n\t}\n}\n\nfunc TestSimpleBackoff(t *testing.T) {\n\tvar tests = []struct {\n\t\tDuration time.Duration\n\t\tContinue bool\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tDuration: 1 * time.Millisecond,\n\t\t\tContinue: true,\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tDuration: 2 * time.Millisecond,\n\t\t\tContinue: true,\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tDuration: 7 * time.Millisecond,\n\t\t\tContinue: true,\n\t\t},\n\t\t// #3\n\t\t{\n\t\t\tDuration: 0,\n\t\t\tContinue: false,\n\t\t},\n\t\t// #4\n\t\t{\n\t\t\tDuration: 0,\n\t\t\tContinue: false,\n\t\t},\n\t}\n\n\tb := NewSimpleBackoff(1, 2, 7)\n\n\tfor i, tt := range tests {\n\t\td, ok := b.Next(i)\n\t\tif got, want := ok, tt.Continue; got != want {\n\t\t\tt.Fatalf(\"#%d: expected %v, got %v\", i, want, got)\n\t\t}\n\t\tif got, want := d, tt.Duration; got != want {\n\t\t\tt.Fatalf(\"#%d: expected %v, got %v\", i, want, got)\n\t\t}\n\t}\n}\n\nfunc TestExponentialBackoff(t *testing.T) {\n\trand.Seed(time.Now().UnixNano())\n\n\tmin := time.Duration(8) * time.Millisecond\n\tmax := time.Duration(256) * time.Millisecond\n\tb := NewExponentialBackoff(min, max)\n\n\tbetween := func(value time.Duration, a, b int) bool {\n\t\tx := int(value / time.Millisecond)\n\t\treturn a <= x && x <= b\n\t}\n\n\tgot, ok := b.Next(0)\n\tif !ok {\n\t\tt.Fatalf(\"expected %v, got %v\", true, ok)\n\t}\n\tif !between(got, 8, 256) {\n\t\tt.Errorf(\"expected [%v..%v], got %v\", 8, 256, got)\n\t}\n\n\tgot, ok = b.Next(1)\n\tif !ok {\n\t\tt.Fatalf(\"expected %v, got %v\", true, ok)\n\t}\n\tif !between(got, 8, 256) {\n\t\tt.Errorf(\"expected [%v..%v], got %v\", 8, 256, got)\n\t}\n\n\tgot, ok = b.Next(2)\n\tif !ok {\n\t\tt.Fatalf(\"expected %v, got %v\", true, ok)\n\t}\n\tif !between(got, 8, 256) {\n\t\tt.Errorf(\"expected [%v..%v], got %v\", 8, 256, got)\n\t}\n\n\tgot, ok = b.Next(3)\n\tif !ok {\n\t\tt.Fatalf(\"expected %v, got %v\", true, ok)\n\t}\n\tif !between(got, 8, 256) {\n\t\tt.Errorf(\"expected [%v..%v], got %v\", 8, 256, got)\n\t}\n\n\tgot, ok = b.Next(4)\n\tif !ok {\n\t\tt.Fatalf(\"expected %v, got %v\", true, ok)\n\t}\n\tif !between(got, 8, 256) {\n\t\tt.Errorf(\"expected [%v..%v], got %v\", 8, 256, got)\n\t}\n\n\tif _, ok := b.Next(5); ok {\n\t\tt.Fatalf(\"expected %v, got %v\", false, ok)\n\t}\n\n\tif _, ok = b.Next(6); ok {\n\t\tt.Fatalf(\"expected %v, got %v\", false, ok)\n\t}\n}\n"
  },
  {
    "path": "bulk.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// BulkService allows for batching bulk requests and sending them to\n// Elasticsearch in one roundtrip. Use the Add method with BulkIndexRequest,\n// BulkUpdateRequest, and BulkDeleteRequest to add bulk requests to a batch,\n// then use Do to send them to Elasticsearch.\n//\n// BulkService will be reset after each Do call. In other words, you can\n// reuse BulkService to send many batches. You do not have to create a new\n// BulkService for each batch.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for more details.\ntype BulkService struct {\n\tclient  *Client\n\tretrier Retrier\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex               string\n\ttyp                 string\n\trequests            []BulkableRequest\n\tpipeline            string\n\ttimeout             string\n\trefresh             string\n\trouting             string\n\twaitForActiveShards string\n\n\t// estimated bulk size in bytes, up to the request index sizeInBytesCursor\n\tsizeInBytes       int64\n\tsizeInBytesCursor int\n}\n\n// NewBulkService initializes a new BulkService.\nfunc NewBulkService(client *Client) *BulkService {\n\tbuilder := &BulkService{\n\t\tclient: client,\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *BulkService) Pretty(pretty bool) *BulkService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *BulkService) Human(human bool) *BulkService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *BulkService) ErrorTrace(errorTrace bool) *BulkService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *BulkService) FilterPath(filterPath ...string) *BulkService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *BulkService) Header(name string, value string) *BulkService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *BulkService) Headers(headers http.Header) *BulkService {\n\ts.headers = headers\n\treturn s\n}\n\n// Reset cleans up the request queue\nfunc (s *BulkService) Reset() {\n\ts.requests = make([]BulkableRequest, 0)\n\ts.sizeInBytes = 0\n\ts.sizeInBytesCursor = 0\n}\n\n// Retrier allows to set specific retry logic for this BulkService.\n// If not specified, it will use the client's default retrier.\nfunc (s *BulkService) Retrier(retrier Retrier) *BulkService {\n\ts.retrier = retrier\n\treturn s\n}\n\n// Index specifies the index to use for all batches. You may also leave\n// this blank and specify the index in the individual bulk requests.\nfunc (s *BulkService) Index(index string) *BulkService {\n\ts.index = index\n\treturn s\n}\n\n// Type specifies the type to use for all batches. You may also leave\n// this blank and specify the type in the individual bulk requests.\nfunc (s *BulkService) Type(typ string) *BulkService {\n\ts.typ = typ\n\treturn s\n}\n\n// Timeout is a global timeout for processing bulk requests. This is a\n// server-side timeout, i.e. it tells Elasticsearch the time after which\n// it should stop processing.\nfunc (s *BulkService) Timeout(timeout string) *BulkService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// Refresh controls when changes made by this request are made visible\n// to search. The allowed values are: \"true\" (refresh the relevant\n// primary and replica shards immediately), \"wait_for\" (wait for the\n// changes to be made visible by a refresh before replying), or \"false\"\n// (no refresh related actions). The default value is \"false\".\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *BulkService) Refresh(refresh string) *BulkService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// Routing specifies the routing value.\nfunc (s *BulkService) Routing(routing string) *BulkService {\n\ts.routing = routing\n\treturn s\n}\n\n// Pipeline specifies the pipeline id to preprocess incoming documents with.\nfunc (s *BulkService) Pipeline(pipeline string) *BulkService {\n\ts.pipeline = pipeline\n\treturn s\n}\n\n// WaitForActiveShards sets the number of shard copies that must be active\n// before proceeding with the bulk operation. Defaults to 1, meaning the\n// primary shard only. Set to `all` for all shard copies, otherwise set to\n// any non-negative value less than or equal to the total number of copies\n// for the shard (number of replicas + 1).\nfunc (s *BulkService) WaitForActiveShards(waitForActiveShards string) *BulkService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// Add adds bulkable requests, i.e. BulkIndexRequest, BulkUpdateRequest,\n// and/or BulkDeleteRequest.\nfunc (s *BulkService) Add(requests ...BulkableRequest) *BulkService {\n\ts.requests = append(s.requests, requests...)\n\treturn s\n}\n\n// EstimatedSizeInBytes returns the estimated size of all bulkable\n// requests added via Add.\nfunc (s *BulkService) EstimatedSizeInBytes() int64 {\n\tif s.sizeInBytesCursor == len(s.requests) {\n\t\treturn s.sizeInBytes\n\t}\n\tfor _, r := range s.requests[s.sizeInBytesCursor:] {\n\t\ts.sizeInBytes += s.estimateSizeInBytes(r)\n\t\ts.sizeInBytesCursor++\n\t}\n\treturn s.sizeInBytes\n}\n\n// estimateSizeInBytes returns the estimates size of the given\n// bulkable request, i.e. BulkIndexRequest, BulkUpdateRequest, and\n// BulkDeleteRequest.\nfunc (s *BulkService) estimateSizeInBytes(r BulkableRequest) int64 {\n\tlines, _ := r.Source()\n\tsize := 0\n\tfor _, line := range lines {\n\t\t// +1 for the \\n\n\t\tsize += len(line) + 1\n\t}\n\treturn int64(size)\n}\n\n// NumberOfActions returns the number of bulkable requests that need to\n// be sent to Elasticsearch on the next batch.\nfunc (s *BulkService) NumberOfActions() int {\n\treturn len(s.requests)\n}\n\nfunc (s *BulkService) bodyAsString() (string, error) {\n\t// Pre-allocate to reduce allocs\n\tvar buf strings.Builder\n\tbuf.Grow(int(s.EstimatedSizeInBytes()))\n\n\tfor _, req := range s.requests {\n\t\tsource, err := req.Source()\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tfor _, line := range source {\n\t\t\tbuf.WriteString(line)\n\t\t\tbuf.WriteByte('\\n')\n\t\t}\n\t}\n\n\treturn buf.String(), nil\n}\n\n// Do sends the batched requests to Elasticsearch. Note that, when successful,\n// you can reuse the BulkService for the next batch as the list of bulk\n// requests is cleared on success.\nfunc (s *BulkService) Do(ctx context.Context) (*BulkResponse, error) {\n\t// No actions?\n\tif s.NumberOfActions() == 0 {\n\t\treturn nil, errors.New(\"elastic: No bulk actions to commit\")\n\t}\n\n\t// Get body\n\tbody, err := s.bodyAsString()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Build url\n\tpath := \"/\"\n\tif len(s.index) > 0 {\n\t\tindex, err := uritemplates.Expand(\"{index}\", map[string]string{\n\t\t\t\"index\": s.index,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tpath += index + \"/\"\n\t}\n\tif len(s.typ) > 0 {\n\t\ttyp, err := uritemplates.Expand(\"{type}\", map[string]string{\n\t\t\t\"type\": s.typ,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tpath += typ + \"/\"\n\t}\n\tpath += \"_bulk\"\n\n\t// Parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.pipeline != \"\" {\n\t\tparams.Set(\"pipeline\", s.pipeline)\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Set(\"refresh\", s.refresh)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\n\t// Get response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:      \"POST\",\n\t\tPath:        path,\n\t\tParams:      params,\n\t\tBody:        body,\n\t\tContentType: \"application/x-ndjson\",\n\t\tRetrier:     s.retrier,\n\t\tHeaders:     s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return results\n\tret := new(BulkResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Reset so the request can be reused\n\ts.Reset()\n\n\treturn ret, nil\n}\n\n// BulkResponse is a response to a bulk execution.\n//\n// Example:\n// {\n//   \"took\":3,\n//   \"errors\":false,\n//   \"items\":[{\n//     \"index\":{\n//       \"_index\":\"index1\",\n//       \"_type\":\"tweet\",\n//       \"_id\":\"1\",\n//       \"_version\":3,\n//       \"status\":201\n//     }\n//   },{\n//     \"index\":{\n//       \"_index\":\"index2\",\n//       \"_type\":\"tweet\",\n//       \"_id\":\"2\",\n//       \"_version\":3,\n//       \"status\":200\n//     }\n//   },{\n//     \"delete\":{\n//       \"_index\":\"index1\",\n//       \"_type\":\"tweet\",\n//       \"_id\":\"1\",\n//       \"_version\":4,\n//       \"status\":200,\n//       \"found\":true\n//     }\n//   },{\n//     \"update\":{\n//       \"_index\":\"index2\",\n//       \"_type\":\"tweet\",\n//       \"_id\":\"2\",\n//       \"_version\":4,\n//       \"status\":200\n//     }\n//   }]\n// }\ntype BulkResponse struct {\n\tTook   int                            `json:\"took,omitempty\"`\n\tErrors bool                           `json:\"errors,omitempty\"`\n\tItems  []map[string]*BulkResponseItem `json:\"items,omitempty\"`\n}\n\n// BulkResponseItem is the result of a single bulk request.\ntype BulkResponseItem struct {\n\tIndex         string        `json:\"_index,omitempty\"`\n\tType          string        `json:\"_type,omitempty\"`\n\tId            string        `json:\"_id,omitempty\"`\n\tVersion       int64         `json:\"_version,omitempty\"`\n\tResult        string        `json:\"result,omitempty\"`\n\tShards        *ShardsInfo   `json:\"_shards,omitempty\"`\n\tSeqNo         int64         `json:\"_seq_no,omitempty\"`\n\tPrimaryTerm   int64         `json:\"_primary_term,omitempty\"`\n\tStatus        int           `json:\"status,omitempty\"`\n\tForcedRefresh bool          `json:\"forced_refresh,omitempty\"`\n\tError         *ErrorDetails `json:\"error,omitempty\"`\n\tGetResult     *GetResult    `json:\"get,omitempty\"`\n}\n\n// Indexed returns all bulk request results of \"index\" actions.\nfunc (r *BulkResponse) Indexed() []*BulkResponseItem {\n\treturn r.ByAction(\"index\")\n}\n\n// Created returns all bulk request results of \"create\" actions.\nfunc (r *BulkResponse) Created() []*BulkResponseItem {\n\treturn r.ByAction(\"create\")\n}\n\n// Updated returns all bulk request results of \"update\" actions.\nfunc (r *BulkResponse) Updated() []*BulkResponseItem {\n\treturn r.ByAction(\"update\")\n}\n\n// Deleted returns all bulk request results of \"delete\" actions.\nfunc (r *BulkResponse) Deleted() []*BulkResponseItem {\n\treturn r.ByAction(\"delete\")\n}\n\n// ByAction returns all bulk request results of a certain action,\n// e.g. \"index\" or \"delete\".\nfunc (r *BulkResponse) ByAction(action string) []*BulkResponseItem {\n\tif r.Items == nil {\n\t\treturn nil\n\t}\n\tvar items []*BulkResponseItem\n\tfor _, item := range r.Items {\n\t\tif result, found := item[action]; found {\n\t\t\titems = append(items, result)\n\t\t}\n\t}\n\treturn items\n}\n\n// ById returns all bulk request results of a given document id,\n// regardless of the action (\"index\", \"delete\" etc.).\nfunc (r *BulkResponse) ById(id string) []*BulkResponseItem {\n\tif r.Items == nil {\n\t\treturn nil\n\t}\n\tvar items []*BulkResponseItem\n\tfor _, item := range r.Items {\n\t\tfor _, result := range item {\n\t\t\tif result.Id == id {\n\t\t\t\titems = append(items, result)\n\t\t\t}\n\t\t}\n\t}\n\treturn items\n}\n\n// Failed returns those items of a bulk response that have errors,\n// i.e. those that don't have a status code between 200 and 299.\nfunc (r *BulkResponse) Failed() []*BulkResponseItem {\n\tif r.Items == nil {\n\t\treturn nil\n\t}\n\tvar errors []*BulkResponseItem\n\tfor _, item := range r.Items {\n\t\tfor _, result := range item {\n\t\t\tif !(result.Status >= 200 && result.Status <= 299) {\n\t\t\t\terrors = append(errors, result)\n\t\t\t}\n\t\t}\n\t}\n\treturn errors\n}\n\n// Succeeded returns those items of a bulk response that have no errors,\n// i.e. those have a status code between 200 and 299.\nfunc (r *BulkResponse) Succeeded() []*BulkResponseItem {\n\tif r.Items == nil {\n\t\treturn nil\n\t}\n\tvar succeeded []*BulkResponseItem\n\tfor _, item := range r.Items {\n\t\tfor _, result := range item {\n\t\t\tif result.Status >= 200 && result.Status <= 299 {\n\t\t\t\tsucceeded = append(succeeded, result)\n\t\t\t}\n\t\t}\n\t}\n\treturn succeeded\n}\n"
  },
  {
    "path": "bulk_create_request.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n//go:generate easyjson bulk_create_request.go\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// BulkCreateRequest is a request to add a new document to Elasticsearch.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for details.\ntype BulkCreateRequest struct {\n\tBulkableRequest\n\tindex           string\n\ttyp             string\n\tid              string\n\topType          string\n\trouting         string\n\tparent          string\n\tversion         *int64 // default is MATCH_ANY\n\tversionType     string // default is \"internal\"\n\tdoc             interface{}\n\tpipeline        string\n\tretryOnConflict *int\n\tifSeqNo         *int64\n\tifPrimaryTerm   *int64\n\n\tsource []string\n\n\tuseEasyJSON bool\n}\n\n//easyjson:json\ntype bulkCreateRequestCommand map[string]bulkCreateRequestCommandOp\n\n//easyjson:json\ntype bulkCreateRequestCommandOp struct {\n\tIndex  string `json:\"_index,omitempty\"`\n\tId     string `json:\"_id,omitempty\"`\n\tType   string `json:\"_type,omitempty\"`\n\tParent string `json:\"parent,omitempty\"`\n\t// RetryOnConflict is \"_retry_on_conflict\" for 6.0 and \"retry_on_conflict\" for 6.1+.\n\tRetryOnConflict *int   `json:\"retry_on_conflict,omitempty\"`\n\tRouting         string `json:\"routing,omitempty\"`\n\tVersion         *int64 `json:\"version,omitempty\"`\n\tVersionType     string `json:\"version_type,omitempty\"`\n\tPipeline        string `json:\"pipeline,omitempty\"`\n\tIfSeqNo         *int64 `json:\"if_seq_no,omitempty\"`\n\tIfPrimaryTerm   *int64 `json:\"if_primary_term,omitempty\"`\n}\n\n// NewBulkCreateRequest returns a new BulkCreateRequest.\n// The operation type is \"create\" by default.\nfunc NewBulkCreateRequest() *BulkCreateRequest {\n\treturn &BulkCreateRequest{\n\t\topType: \"create\",\n\t}\n}\n\n// UseEasyJSON is an experimental setting that enables serialization\n// with github.com/mailru/easyjson, which should in faster serialization\n// time and less allocations, but removed compatibility with encoding/json,\n// usage of unsafe etc. See https://github.com/mailru/easyjson#issues-notes-and-limitations\n// for details. This setting is disabled by default.\nfunc (r *BulkCreateRequest) UseEasyJSON(enable bool) *BulkCreateRequest {\n\tr.useEasyJSON = enable\n\treturn r\n}\n\n// Index specifies the Elasticsearch index to use for this create request.\n// If unspecified, the index set on the BulkService will be used.\nfunc (r *BulkCreateRequest) Index(index string) *BulkCreateRequest {\n\tr.index = index\n\tr.source = nil\n\treturn r\n}\n\n// Type specifies the Elasticsearch type to use for this create request.\n// If unspecified, the type set on the BulkService will be used.\nfunc (r *BulkCreateRequest) Type(typ string) *BulkCreateRequest {\n\tr.typ = typ\n\tr.source = nil\n\treturn r\n}\n\n// Id specifies the identifier of the document to create.\nfunc (r *BulkCreateRequest) Id(id string) *BulkCreateRequest {\n\tr.id = id\n\tr.source = nil\n\treturn r\n}\n\n// Routing specifies a routing value for the request.\nfunc (r *BulkCreateRequest) Routing(routing string) *BulkCreateRequest {\n\tr.routing = routing\n\tr.source = nil\n\treturn r\n}\n\n// Parent specifies the identifier of the parent document (if available).\nfunc (r *BulkCreateRequest) Parent(parent string) *BulkCreateRequest {\n\tr.parent = parent\n\tr.source = nil\n\treturn r\n}\n\n// Version indicates the version of the document as part of an optimistic\n// concurrency model.\nfunc (r *BulkCreateRequest) Version(version int64) *BulkCreateRequest {\n\tv := version\n\tr.version = &v\n\tr.source = nil\n\treturn r\n}\n\n// VersionType specifies how versions are created. It can be e.g. internal,\n// external, external_gte, or force.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-index_.html#index-versioning\n// for details.\nfunc (r *BulkCreateRequest) VersionType(versionType string) *BulkCreateRequest {\n\tr.versionType = versionType\n\tr.source = nil\n\treturn r\n}\n\n// Doc specifies the document to create.\nfunc (r *BulkCreateRequest) Doc(doc interface{}) *BulkCreateRequest {\n\tr.doc = doc\n\tr.source = nil\n\treturn r\n}\n\n// RetryOnConflict specifies how often to retry in case of a version conflict.\nfunc (r *BulkCreateRequest) RetryOnConflict(retryOnConflict int) *BulkCreateRequest {\n\tr.retryOnConflict = &retryOnConflict\n\tr.source = nil\n\treturn r\n}\n\n// Pipeline to use while processing the request.\nfunc (r *BulkCreateRequest) Pipeline(pipeline string) *BulkCreateRequest {\n\tr.pipeline = pipeline\n\tr.source = nil\n\treturn r\n}\n\n// IfSeqNo indicates to only perform the create operation if the last\n// operation that has changed the document has the specified sequence number.\nfunc (r *BulkCreateRequest) IfSeqNo(ifSeqNo int64) *BulkCreateRequest {\n\tr.ifSeqNo = &ifSeqNo\n\treturn r\n}\n\n// IfPrimaryTerm indicates to only perform the create operation if the\n// last operation that has changed the document has the specified primary term.\nfunc (r *BulkCreateRequest) IfPrimaryTerm(ifPrimaryTerm int64) *BulkCreateRequest {\n\tr.ifPrimaryTerm = &ifPrimaryTerm\n\treturn r\n}\n\n// String returns the on-wire representation of the create request,\n// concatenated as a single string.\nfunc (r *BulkCreateRequest) String() string {\n\tlines, err := r.Source()\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"error: %v\", err)\n\t}\n\treturn strings.Join(lines, \"\\n\")\n}\n\n// Source returns the on-wire representation of the create request,\n// split into an action-and-meta-data line and an (optional) source line.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for details.\nfunc (r *BulkCreateRequest) Source() ([]string, error) {\n\t// { \"create\" : { \"_index\" : \"test\", \"_type\" : \"type1\", \"_id\" : \"1\" } }\n\t// { \"field1\" : \"value1\" }\n\n\tif r.source != nil {\n\t\treturn r.source, nil\n\t}\n\n\tlines := make([]string, 2)\n\n\t// \"index\" ...\n\tindexCommand := bulkCreateRequestCommandOp{\n\t\tIndex:           r.index,\n\t\tType:            r.typ,\n\t\tId:              r.id,\n\t\tRouting:         r.routing,\n\t\tParent:          r.parent,\n\t\tVersion:         r.version,\n\t\tVersionType:     r.versionType,\n\t\tRetryOnConflict: r.retryOnConflict,\n\t\tPipeline:        r.pipeline,\n\t\tIfSeqNo:         r.ifSeqNo,\n\t\tIfPrimaryTerm:   r.ifPrimaryTerm,\n\t}\n\tcommand := bulkCreateRequestCommand{\n\t\tr.opType: indexCommand,\n\t}\n\n\tvar err error\n\tvar body []byte\n\tif r.useEasyJSON {\n\t\t// easyjson\n\t\tbody, err = command.MarshalJSON()\n\t} else {\n\t\t// encoding/json\n\t\tbody, err = json.Marshal(command)\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlines[0] = string(body)\n\n\t// \"field1\" ...\n\tif r.doc != nil {\n\t\tswitch t := r.doc.(type) {\n\t\tdefault:\n\t\t\tbody, err := json.Marshal(r.doc)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tlines[1] = string(body)\n\t\tcase json.RawMessage:\n\t\t\tlines[1] = string(t)\n\t\tcase *json.RawMessage:\n\t\t\tlines[1] = string(*t)\n\t\tcase string:\n\t\t\tlines[1] = t\n\t\tcase *string:\n\t\t\tlines[1] = *t\n\t\t}\n\t} else {\n\t\tlines[1] = \"{}\"\n\t}\n\n\tr.source = lines\n\treturn lines, nil\n}\n"
  },
  {
    "path": "bulk_create_request_easyjson.go",
    "content": "// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.\n\npackage elastic\n\nimport (\n\tjson \"encoding/json\"\n\teasyjson \"github.com/mailru/easyjson\"\n\tjlexer \"github.com/mailru/easyjson/jlexer\"\n\tjwriter \"github.com/mailru/easyjson/jwriter\"\n)\n\n// suppress unused package warning\nvar (\n\t_ *json.RawMessage\n\t_ *jlexer.Lexer\n\t_ *jwriter.Writer\n\t_ easyjson.Marshaler\n)\n\nfunc easyjson29a8ef77DecodeGithubComOlivereElasticV7(in *jlexer.Lexer, out *bulkCreateRequestCommandOp) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tif isTopLevel {\n\t\t\tin.Consumed()\n\t\t}\n\t\tin.Skip()\n\t\treturn\n\t}\n\tin.Delim('{')\n\tfor !in.IsDelim('}') {\n\t\tkey := in.UnsafeFieldName(false)\n\t\tin.WantColon()\n\t\tif in.IsNull() {\n\t\t\tin.Skip()\n\t\t\tin.WantComma()\n\t\t\tcontinue\n\t\t}\n\t\tswitch key {\n\t\tcase \"_index\":\n\t\t\tout.Index = string(in.String())\n\t\tcase \"_id\":\n\t\t\tout.Id = string(in.String())\n\t\tcase \"_type\":\n\t\t\tout.Type = string(in.String())\n\t\tcase \"parent\":\n\t\t\tout.Parent = string(in.String())\n\t\tcase \"retry_on_conflict\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.RetryOnConflict = nil\n\t\t\t} else {\n\t\t\t\tif out.RetryOnConflict == nil {\n\t\t\t\t\tout.RetryOnConflict = new(int)\n\t\t\t\t}\n\t\t\t\t*out.RetryOnConflict = int(in.Int())\n\t\t\t}\n\t\tcase \"routing\":\n\t\t\tout.Routing = string(in.String())\n\t\tcase \"version\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.Version = nil\n\t\t\t} else {\n\t\t\t\tif out.Version == nil {\n\t\t\t\t\tout.Version = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.Version = int64(in.Int64())\n\t\t\t}\n\t\tcase \"version_type\":\n\t\t\tout.VersionType = string(in.String())\n\t\tcase \"pipeline\":\n\t\t\tout.Pipeline = string(in.String())\n\t\tcase \"if_seq_no\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.IfSeqNo = nil\n\t\t\t} else {\n\t\t\t\tif out.IfSeqNo == nil {\n\t\t\t\t\tout.IfSeqNo = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.IfSeqNo = int64(in.Int64())\n\t\t\t}\n\t\tcase \"if_primary_term\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.IfPrimaryTerm = nil\n\t\t\t} else {\n\t\t\t\tif out.IfPrimaryTerm == nil {\n\t\t\t\t\tout.IfPrimaryTerm = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.IfPrimaryTerm = int64(in.Int64())\n\t\t\t}\n\t\tdefault:\n\t\t\tin.SkipRecursive()\n\t\t}\n\t\tin.WantComma()\n\t}\n\tin.Delim('}')\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson29a8ef77EncodeGithubComOlivereElasticV7(out *jwriter.Writer, in bulkCreateRequestCommandOp) {\n\tout.RawByte('{')\n\tfirst := true\n\t_ = first\n\tif in.Index != \"\" {\n\t\tconst prefix string = \",\\\"_index\\\":\"\n\t\tfirst = false\n\t\tout.RawString(prefix[1:])\n\t\tout.String(string(in.Index))\n\t}\n\tif in.Id != \"\" {\n\t\tconst prefix string = \",\\\"_id\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Id))\n\t}\n\tif in.Type != \"\" {\n\t\tconst prefix string = \",\\\"_type\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Type))\n\t}\n\tif in.Parent != \"\" {\n\t\tconst prefix string = \",\\\"parent\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Parent))\n\t}\n\tif in.RetryOnConflict != nil {\n\t\tconst prefix string = \",\\\"retry_on_conflict\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int(int(*in.RetryOnConflict))\n\t}\n\tif in.Routing != \"\" {\n\t\tconst prefix string = \",\\\"routing\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Routing))\n\t}\n\tif in.Version != nil {\n\t\tconst prefix string = \",\\\"version\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.Version))\n\t}\n\tif in.VersionType != \"\" {\n\t\tconst prefix string = \",\\\"version_type\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.VersionType))\n\t}\n\tif in.Pipeline != \"\" {\n\t\tconst prefix string = \",\\\"pipeline\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Pipeline))\n\t}\n\tif in.IfSeqNo != nil {\n\t\tconst prefix string = \",\\\"if_seq_no\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.IfSeqNo))\n\t}\n\tif in.IfPrimaryTerm != nil {\n\t\tconst prefix string = \",\\\"if_primary_term\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.IfPrimaryTerm))\n\t}\n\tout.RawByte('}')\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v bulkCreateRequestCommandOp) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson29a8ef77EncodeGithubComOlivereElasticV7(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v bulkCreateRequestCommandOp) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson29a8ef77EncodeGithubComOlivereElasticV7(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *bulkCreateRequestCommandOp) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson29a8ef77DecodeGithubComOlivereElasticV7(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *bulkCreateRequestCommandOp) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson29a8ef77DecodeGithubComOlivereElasticV7(l, v)\n}\nfunc easyjson29a8ef77DecodeGithubComOlivereElasticV71(in *jlexer.Lexer, out *bulkCreateRequestCommand) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tin.Skip()\n\t} else {\n\t\tin.Delim('{')\n\t\t*out = make(bulkCreateRequestCommand)\n\t\tfor !in.IsDelim('}') {\n\t\t\tkey := string(in.String())\n\t\t\tin.WantColon()\n\t\t\tvar v1 bulkCreateRequestCommandOp\n\t\t\t(v1).UnmarshalEasyJSON(in)\n\t\t\t(*out)[key] = v1\n\t\t\tin.WantComma()\n\t\t}\n\t\tin.Delim('}')\n\t}\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson29a8ef77EncodeGithubComOlivereElasticV71(out *jwriter.Writer, in bulkCreateRequestCommand) {\n\tif in == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {\n\t\tout.RawString(`null`)\n\t} else {\n\t\tout.RawByte('{')\n\t\tv2First := true\n\t\tfor v2Name, v2Value := range in {\n\t\t\tif v2First {\n\t\t\t\tv2First = false\n\t\t\t} else {\n\t\t\t\tout.RawByte(',')\n\t\t\t}\n\t\t\tout.String(string(v2Name))\n\t\t\tout.RawByte(':')\n\t\t\t(v2Value).MarshalEasyJSON(out)\n\t\t}\n\t\tout.RawByte('}')\n\t}\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v bulkCreateRequestCommand) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson29a8ef77EncodeGithubComOlivereElasticV71(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v bulkCreateRequestCommand) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson29a8ef77EncodeGithubComOlivereElasticV71(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *bulkCreateRequestCommand) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson29a8ef77DecodeGithubComOlivereElasticV71(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *bulkCreateRequestCommand) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson29a8ef77DecodeGithubComOlivereElasticV71(l, v)\n}\n"
  },
  {
    "path": "bulk_create_request_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestBulkCreateRequestSerialization(t *testing.T) {\n\ttests := []struct {\n\t\tRequest  BulkableRequest\n\t\tExpected []string\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tRequest: NewBulkCreateRequest().Index(\"index1\").Id(\"1\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"create\":{\"_index\":\"index1\",\"_id\":\"1\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tRequest: NewBulkCreateRequest().Index(\"index1\").Id(\"1\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"create\":{\"_index\":\"index1\",\"_id\":\"1\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tRequest: NewBulkCreateRequest().Index(\"index1\").Id(\"1\").RetryOnConflict(42).\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"create\":{\"_index\":\"index1\",\"_id\":\"1\",\"retry_on_conflict\":42}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #3\n\t\t{\n\t\t\tRequest: NewBulkCreateRequest().Index(\"index1\").Id(\"1\").Pipeline(\"my_pipeline\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"create\":{\"_index\":\"index1\",\"_id\":\"1\",\"pipeline\":\"my_pipeline\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #4\n\t\t{\n\t\t\tRequest: NewBulkCreateRequest().Index(\"index1\").Id(\"1\").\n\t\t\t\tRouting(\"123\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"create\":{\"_index\":\"index1\",\"_id\":\"1\",\"routing\":\"123\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #5\n\t\t{\n\t\t\tRequest: NewBulkCreateRequest().Index(\"index1\").Type(\"doc\").Id(\"1\").\n\t\t\t\tVersion(0).\n\t\t\t\tVersionType(\"external\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"create\":{\"_index\":\"index1\",\"_id\":\"1\",\"_type\":\"doc\",\"version\":0,\"version_type\":\"external\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tlines, err := test.Request.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"case #%d: expected no error, got: %v\", i, err)\n\t\t}\n\t\tif lines == nil {\n\t\t\tt.Fatalf(\"case #%d: expected lines, got nil\", i)\n\t\t}\n\t\tif len(lines) != len(test.Expected) {\n\t\t\tt.Fatalf(\"case #%d: expected %d lines, got %d\", i, len(test.Expected), len(lines))\n\t\t}\n\t\tfor j, line := range lines {\n\t\t\tif line != test.Expected[j] {\n\t\t\t\tt.Errorf(\"case #%d: expected line #%d to be %s, got: %s\", i, j, test.Expected[j], line)\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar bulkCreateRequestSerializationResult string\n\nfunc BenchmarkBulkCreateRequestSerialization(b *testing.B) {\n\tb.Run(\"stdlib\", func(b *testing.B) {\n\t\tr := NewBulkCreateRequest().Index(testIndexName).Id(\"1\").\n\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)})\n\t\tbenchmarkBulkCreateRequestSerialization(b, r.UseEasyJSON(false))\n\t})\n\tb.Run(\"easyjson\", func(b *testing.B) {\n\t\tr := NewBulkCreateRequest().Index(testIndexName).Id(\"1\").\n\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)})\n\t\tbenchmarkBulkCreateRequestSerialization(b, r.UseEasyJSON(true))\n\t})\n}\n\nfunc benchmarkBulkCreateRequestSerialization(b *testing.B, r *BulkCreateRequest) {\n\tvar s string\n\tfor n := 0; n < b.N; n++ {\n\t\ts = r.String()\n\t\tr.source = nil // Don't let caching spoil the benchmark\n\t}\n\tbulkCreateRequestSerializationResult = s // ensure the compiler doesn't optimize\n\tb.ReportAllocs()\n}\n"
  },
  {
    "path": "bulk_delete_request.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n//go:generate easyjson bulk_delete_request.go\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// -- Bulk delete request --\n\n// BulkDeleteRequest is a request to remove a document from Elasticsearch.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for details.\ntype BulkDeleteRequest struct {\n\tBulkableRequest\n\tindex         string\n\ttyp           string\n\tid            string\n\tparent        string\n\trouting       string\n\tversion       int64  // default is MATCH_ANY\n\tversionType   string // default is \"internal\"\n\tifSeqNo       *int64\n\tifPrimaryTerm *int64\n\n\tsource []string\n\n\tuseEasyJSON bool\n}\n\n//easyjson:json\ntype bulkDeleteRequestCommand map[string]bulkDeleteRequestCommandOp\n\n//easyjson:json\ntype bulkDeleteRequestCommandOp struct {\n\tIndex         string `json:\"_index,omitempty\"`\n\tType          string `json:\"_type,omitempty\"`\n\tId            string `json:\"_id,omitempty\"`\n\tParent        string `json:\"parent,omitempty\"`\n\tRouting       string `json:\"routing,omitempty\"`\n\tVersion       int64  `json:\"version,omitempty\"`\n\tVersionType   string `json:\"version_type,omitempty\"`\n\tIfSeqNo       *int64 `json:\"if_seq_no,omitempty\"`\n\tIfPrimaryTerm *int64 `json:\"if_primary_term,omitempty\"`\n}\n\n// NewBulkDeleteRequest returns a new BulkDeleteRequest.\nfunc NewBulkDeleteRequest() *BulkDeleteRequest {\n\treturn &BulkDeleteRequest{}\n}\n\n// UseEasyJSON is an experimental setting that enables serialization\n// with github.com/mailru/easyjson, which should in faster serialization\n// time and less allocations, but removed compatibility with encoding/json,\n// usage of unsafe etc. See https://github.com/mailru/easyjson#issues-notes-and-limitations\n// for details. This setting is disabled by default.\nfunc (r *BulkDeleteRequest) UseEasyJSON(enable bool) *BulkDeleteRequest {\n\tr.useEasyJSON = enable\n\treturn r\n}\n\n// Index specifies the Elasticsearch index to use for this delete request.\n// If unspecified, the index set on the BulkService will be used.\nfunc (r *BulkDeleteRequest) Index(index string) *BulkDeleteRequest {\n\tr.index = index\n\tr.source = nil\n\treturn r\n}\n\n// Type specifies the Elasticsearch type to use for this delete request.\n// If unspecified, the type set on the BulkService will be used.\nfunc (r *BulkDeleteRequest) Type(typ string) *BulkDeleteRequest {\n\tr.typ = typ\n\tr.source = nil\n\treturn r\n}\n\n// Id specifies the identifier of the document to delete.\nfunc (r *BulkDeleteRequest) Id(id string) *BulkDeleteRequest {\n\tr.id = id\n\tr.source = nil\n\treturn r\n}\n\n// Parent specifies the parent of the request, which is used in parent/child\n// mappings.\nfunc (r *BulkDeleteRequest) Parent(parent string) *BulkDeleteRequest {\n\tr.parent = parent\n\tr.source = nil\n\treturn r\n}\n\n// Routing specifies a routing value for the request.\nfunc (r *BulkDeleteRequest) Routing(routing string) *BulkDeleteRequest {\n\tr.routing = routing\n\tr.source = nil\n\treturn r\n}\n\n// Version indicates the version to be deleted as part of an optimistic\n// concurrency model.\nfunc (r *BulkDeleteRequest) Version(version int64) *BulkDeleteRequest {\n\tr.version = version\n\tr.source = nil\n\treturn r\n}\n\n// VersionType can be \"internal\" (default), \"external\", \"external_gte\",\n// or \"external_gt\".\nfunc (r *BulkDeleteRequest) VersionType(versionType string) *BulkDeleteRequest {\n\tr.versionType = versionType\n\tr.source = nil\n\treturn r\n}\n\n// IfSeqNo indicates to only perform the delete operation if the last\n// operation that has changed the document has the specified sequence number.\nfunc (r *BulkDeleteRequest) IfSeqNo(ifSeqNo int64) *BulkDeleteRequest {\n\tr.ifSeqNo = &ifSeqNo\n\treturn r\n}\n\n// IfPrimaryTerm indicates to only perform the delete operation if the\n// last operation that has changed the document has the specified primary term.\nfunc (r *BulkDeleteRequest) IfPrimaryTerm(ifPrimaryTerm int64) *BulkDeleteRequest {\n\tr.ifPrimaryTerm = &ifPrimaryTerm\n\treturn r\n}\n\n// String returns the on-wire representation of the delete request,\n// concatenated as a single string.\nfunc (r *BulkDeleteRequest) String() string {\n\tlines, err := r.Source()\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"error: %v\", err)\n\t}\n\treturn strings.Join(lines, \"\\n\")\n}\n\n// Source returns the on-wire representation of the delete request,\n// split into an action-and-meta-data line and an (optional) source line.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for details.\nfunc (r *BulkDeleteRequest) Source() ([]string, error) {\n\tif r.source != nil {\n\t\treturn r.source, nil\n\t}\n\tcommand := bulkDeleteRequestCommand{\n\t\t\"delete\": bulkDeleteRequestCommandOp{\n\t\t\tIndex:         r.index,\n\t\t\tType:          r.typ,\n\t\t\tId:            r.id,\n\t\t\tRouting:       r.routing,\n\t\t\tParent:        r.parent,\n\t\t\tVersion:       r.version,\n\t\t\tVersionType:   r.versionType,\n\t\t\tIfSeqNo:       r.ifSeqNo,\n\t\t\tIfPrimaryTerm: r.ifPrimaryTerm,\n\t\t},\n\t}\n\n\tvar err error\n\tvar body []byte\n\tif r.useEasyJSON {\n\t\t// easyjson\n\t\tbody, err = command.MarshalJSON()\n\t} else {\n\t\t// encoding/json\n\t\tbody, err = json.Marshal(command)\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlines := []string{string(body)}\n\tr.source = lines\n\n\treturn lines, nil\n}\n"
  },
  {
    "path": "bulk_delete_request_easyjson.go",
    "content": "// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.\n\npackage elastic\n\nimport (\n\tjson \"encoding/json\"\n\teasyjson \"github.com/mailru/easyjson\"\n\tjlexer \"github.com/mailru/easyjson/jlexer\"\n\tjwriter \"github.com/mailru/easyjson/jwriter\"\n)\n\n// suppress unused package warning\nvar (\n\t_ *json.RawMessage\n\t_ *jlexer.Lexer\n\t_ *jwriter.Writer\n\t_ easyjson.Marshaler\n)\n\nfunc easyjson8092efb6DecodeGithubComOlivereElasticV7(in *jlexer.Lexer, out *bulkDeleteRequestCommandOp) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tif isTopLevel {\n\t\t\tin.Consumed()\n\t\t}\n\t\tin.Skip()\n\t\treturn\n\t}\n\tin.Delim('{')\n\tfor !in.IsDelim('}') {\n\t\tkey := in.UnsafeFieldName(false)\n\t\tin.WantColon()\n\t\tif in.IsNull() {\n\t\t\tin.Skip()\n\t\t\tin.WantComma()\n\t\t\tcontinue\n\t\t}\n\t\tswitch key {\n\t\tcase \"_index\":\n\t\t\tout.Index = string(in.String())\n\t\tcase \"_type\":\n\t\t\tout.Type = string(in.String())\n\t\tcase \"_id\":\n\t\t\tout.Id = string(in.String())\n\t\tcase \"parent\":\n\t\t\tout.Parent = string(in.String())\n\t\tcase \"routing\":\n\t\t\tout.Routing = string(in.String())\n\t\tcase \"version\":\n\t\t\tout.Version = int64(in.Int64())\n\t\tcase \"version_type\":\n\t\t\tout.VersionType = string(in.String())\n\t\tcase \"if_seq_no\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.IfSeqNo = nil\n\t\t\t} else {\n\t\t\t\tif out.IfSeqNo == nil {\n\t\t\t\t\tout.IfSeqNo = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.IfSeqNo = int64(in.Int64())\n\t\t\t}\n\t\tcase \"if_primary_term\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.IfPrimaryTerm = nil\n\t\t\t} else {\n\t\t\t\tif out.IfPrimaryTerm == nil {\n\t\t\t\t\tout.IfPrimaryTerm = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.IfPrimaryTerm = int64(in.Int64())\n\t\t\t}\n\t\tdefault:\n\t\t\tin.SkipRecursive()\n\t\t}\n\t\tin.WantComma()\n\t}\n\tin.Delim('}')\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson8092efb6EncodeGithubComOlivereElasticV7(out *jwriter.Writer, in bulkDeleteRequestCommandOp) {\n\tout.RawByte('{')\n\tfirst := true\n\t_ = first\n\tif in.Index != \"\" {\n\t\tconst prefix string = \",\\\"_index\\\":\"\n\t\tfirst = false\n\t\tout.RawString(prefix[1:])\n\t\tout.String(string(in.Index))\n\t}\n\tif in.Type != \"\" {\n\t\tconst prefix string = \",\\\"_type\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Type))\n\t}\n\tif in.Id != \"\" {\n\t\tconst prefix string = \",\\\"_id\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Id))\n\t}\n\tif in.Parent != \"\" {\n\t\tconst prefix string = \",\\\"parent\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Parent))\n\t}\n\tif in.Routing != \"\" {\n\t\tconst prefix string = \",\\\"routing\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Routing))\n\t}\n\tif in.Version != 0 {\n\t\tconst prefix string = \",\\\"version\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(in.Version))\n\t}\n\tif in.VersionType != \"\" {\n\t\tconst prefix string = \",\\\"version_type\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.VersionType))\n\t}\n\tif in.IfSeqNo != nil {\n\t\tconst prefix string = \",\\\"if_seq_no\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.IfSeqNo))\n\t}\n\tif in.IfPrimaryTerm != nil {\n\t\tconst prefix string = \",\\\"if_primary_term\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.IfPrimaryTerm))\n\t}\n\tout.RawByte('}')\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v bulkDeleteRequestCommandOp) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson8092efb6EncodeGithubComOlivereElasticV7(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v bulkDeleteRequestCommandOp) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson8092efb6EncodeGithubComOlivereElasticV7(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *bulkDeleteRequestCommandOp) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson8092efb6DecodeGithubComOlivereElasticV7(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *bulkDeleteRequestCommandOp) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson8092efb6DecodeGithubComOlivereElasticV7(l, v)\n}\nfunc easyjson8092efb6DecodeGithubComOlivereElasticV71(in *jlexer.Lexer, out *bulkDeleteRequestCommand) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tin.Skip()\n\t} else {\n\t\tin.Delim('{')\n\t\t*out = make(bulkDeleteRequestCommand)\n\t\tfor !in.IsDelim('}') {\n\t\t\tkey := string(in.String())\n\t\t\tin.WantColon()\n\t\t\tvar v1 bulkDeleteRequestCommandOp\n\t\t\t(v1).UnmarshalEasyJSON(in)\n\t\t\t(*out)[key] = v1\n\t\t\tin.WantComma()\n\t\t}\n\t\tin.Delim('}')\n\t}\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson8092efb6EncodeGithubComOlivereElasticV71(out *jwriter.Writer, in bulkDeleteRequestCommand) {\n\tif in == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {\n\t\tout.RawString(`null`)\n\t} else {\n\t\tout.RawByte('{')\n\t\tv2First := true\n\t\tfor v2Name, v2Value := range in {\n\t\t\tif v2First {\n\t\t\t\tv2First = false\n\t\t\t} else {\n\t\t\t\tout.RawByte(',')\n\t\t\t}\n\t\t\tout.String(string(v2Name))\n\t\t\tout.RawByte(':')\n\t\t\t(v2Value).MarshalEasyJSON(out)\n\t\t}\n\t\tout.RawByte('}')\n\t}\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v bulkDeleteRequestCommand) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson8092efb6EncodeGithubComOlivereElasticV71(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v bulkDeleteRequestCommand) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson8092efb6EncodeGithubComOlivereElasticV71(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *bulkDeleteRequestCommand) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson8092efb6DecodeGithubComOlivereElasticV71(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *bulkDeleteRequestCommand) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson8092efb6DecodeGithubComOlivereElasticV71(l, v)\n}\n"
  },
  {
    "path": "bulk_delete_request_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestBulkDeleteRequestSerialization(t *testing.T) {\n\ttests := []struct {\n\t\tRequest  BulkableRequest\n\t\tExpected []string\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tRequest: NewBulkDeleteRequest().Index(\"index1\").Id(\"1\"),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"delete\":{\"_index\":\"index1\",\"_id\":\"1\"}}`,\n\t\t\t},\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tRequest: NewBulkDeleteRequest().Index(\"index1\").Id(\"1\").Parent(\"2\"),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"delete\":{\"_index\":\"index1\",\"_id\":\"1\",\"parent\":\"2\"}}`,\n\t\t\t},\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tRequest: NewBulkDeleteRequest().Index(\"index1\").Id(\"1\").Routing(\"3\"),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"delete\":{\"_index\":\"index1\",\"_id\":\"1\",\"routing\":\"3\"}}`,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tlines, err := test.Request.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"case #%d: expected no error, got: %v\", i, err)\n\t\t}\n\t\tif lines == nil {\n\t\t\tt.Fatalf(\"case #%d: expected lines, got nil\", i)\n\t\t}\n\t\tif len(lines) != len(test.Expected) {\n\t\t\tt.Fatalf(\"case #%d: expected %d lines, got %d\", i, len(test.Expected), len(lines))\n\t\t}\n\t\tfor j, line := range lines {\n\t\t\tif line != test.Expected[j] {\n\t\t\t\tt.Errorf(\"case #%d: expected line #%d to be %s, got: %s\", i, j, test.Expected[j], line)\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar bulkDeleteRequestSerializationResult string\n\nfunc BenchmarkBulkDeleteRequestSerialization(b *testing.B) {\n\tb.Run(\"stdlib\", func(b *testing.B) {\n\t\tr := NewBulkDeleteRequest().Index(testIndexName).Id(\"1\")\n\t\tbenchmarkBulkDeleteRequestSerialization(b, r.UseEasyJSON(false))\n\t})\n\tb.Run(\"easyjson\", func(b *testing.B) {\n\t\tr := NewBulkDeleteRequest().Index(testIndexName).Id(\"1\")\n\t\tbenchmarkBulkDeleteRequestSerialization(b, r.UseEasyJSON(true))\n\t})\n}\n\nfunc benchmarkBulkDeleteRequestSerialization(b *testing.B, r *BulkDeleteRequest) {\n\tvar s string\n\tfor n := 0; n < b.N; n++ {\n\t\ts = r.String()\n\t\tr.source = nil // Don't let caching spoil the benchmark\n\t}\n\tbulkDeleteRequestSerializationResult = s // ensure the compiler doesn't optimize\n\tb.ReportAllocs()\n}\n"
  },
  {
    "path": "bulk_index_request.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n//go:generate easyjson bulk_index_request.go\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// BulkIndexRequest is a request to add or replace a document to Elasticsearch.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for details.\ntype BulkIndexRequest struct {\n\tBulkableRequest\n\tindex           string\n\ttyp             string\n\tid              string\n\topType          string\n\trouting         string\n\tparent          string\n\tversion         *int64 // default is MATCH_ANY\n\tversionType     string // default is \"internal\"\n\tdoc             interface{}\n\tpipeline        string\n\tretryOnConflict *int\n\tifSeqNo         *int64\n\tifPrimaryTerm   *int64\n\n\tsource []string\n\n\tuseEasyJSON bool\n}\n\n//easyjson:json\ntype bulkIndexRequestCommand map[string]bulkIndexRequestCommandOp\n\n//easyjson:json\ntype bulkIndexRequestCommandOp struct {\n\tIndex  string `json:\"_index,omitempty\"`\n\tId     string `json:\"_id,omitempty\"`\n\tType   string `json:\"_type,omitempty\"`\n\tParent string `json:\"parent,omitempty\"`\n\t// RetryOnConflict is \"_retry_on_conflict\" for 6.0 and \"retry_on_conflict\" for 6.1+.\n\tRetryOnConflict *int   `json:\"retry_on_conflict,omitempty\"`\n\tRouting         string `json:\"routing,omitempty\"`\n\tVersion         *int64 `json:\"version,omitempty\"`\n\tVersionType     string `json:\"version_type,omitempty\"`\n\tPipeline        string `json:\"pipeline,omitempty\"`\n\tIfSeqNo         *int64 `json:\"if_seq_no,omitempty\"`\n\tIfPrimaryTerm   *int64 `json:\"if_primary_term,omitempty\"`\n}\n\n// NewBulkIndexRequest returns a new BulkIndexRequest.\n// The operation type is \"index\" by default.\nfunc NewBulkIndexRequest() *BulkIndexRequest {\n\treturn &BulkIndexRequest{\n\t\topType: \"index\",\n\t}\n}\n\n// UseEasyJSON is an experimental setting that enables serialization\n// with github.com/mailru/easyjson, which should in faster serialization\n// time and less allocations, but removed compatibility with encoding/json,\n// usage of unsafe etc. See https://github.com/mailru/easyjson#issues-notes-and-limitations\n// for details. This setting is disabled by default.\nfunc (r *BulkIndexRequest) UseEasyJSON(enable bool) *BulkIndexRequest {\n\tr.useEasyJSON = enable\n\treturn r\n}\n\n// Index specifies the Elasticsearch index to use for this index request.\n// If unspecified, the index set on the BulkService will be used.\nfunc (r *BulkIndexRequest) Index(index string) *BulkIndexRequest {\n\tr.index = index\n\tr.source = nil\n\treturn r\n}\n\n// Type specifies the Elasticsearch type to use for this index request.\n// If unspecified, the type set on the BulkService will be used.\nfunc (r *BulkIndexRequest) Type(typ string) *BulkIndexRequest {\n\tr.typ = typ\n\tr.source = nil\n\treturn r\n}\n\n// Id specifies the identifier of the document to index.\nfunc (r *BulkIndexRequest) Id(id string) *BulkIndexRequest {\n\tr.id = id\n\tr.source = nil\n\treturn r\n}\n\n// OpType specifies if this request should follow create-only or upsert\n// behavior. This follows the OpType of the standard document index API.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-index_.html#operation-type\n// for details.\nfunc (r *BulkIndexRequest) OpType(opType string) *BulkIndexRequest {\n\tr.opType = opType\n\tr.source = nil\n\treturn r\n}\n\n// Routing specifies a routing value for the request.\nfunc (r *BulkIndexRequest) Routing(routing string) *BulkIndexRequest {\n\tr.routing = routing\n\tr.source = nil\n\treturn r\n}\n\n// Parent specifies the identifier of the parent document (if available).\nfunc (r *BulkIndexRequest) Parent(parent string) *BulkIndexRequest {\n\tr.parent = parent\n\tr.source = nil\n\treturn r\n}\n\n// Version indicates the version of the document as part of an optimistic\n// concurrency model.\nfunc (r *BulkIndexRequest) Version(version int64) *BulkIndexRequest {\n\tv := version\n\tr.version = &v\n\tr.source = nil\n\treturn r\n}\n\n// VersionType specifies how versions are created. It can be e.g. internal,\n// external, external_gte, or force.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-index_.html#index-versioning\n// for details.\nfunc (r *BulkIndexRequest) VersionType(versionType string) *BulkIndexRequest {\n\tr.versionType = versionType\n\tr.source = nil\n\treturn r\n}\n\n// Doc specifies the document to index.\nfunc (r *BulkIndexRequest) Doc(doc interface{}) *BulkIndexRequest {\n\tr.doc = doc\n\tr.source = nil\n\treturn r\n}\n\n// RetryOnConflict specifies how often to retry in case of a version conflict.\nfunc (r *BulkIndexRequest) RetryOnConflict(retryOnConflict int) *BulkIndexRequest {\n\tr.retryOnConflict = &retryOnConflict\n\tr.source = nil\n\treturn r\n}\n\n// Pipeline to use while processing the request.\nfunc (r *BulkIndexRequest) Pipeline(pipeline string) *BulkIndexRequest {\n\tr.pipeline = pipeline\n\tr.source = nil\n\treturn r\n}\n\n// IfSeqNo indicates to only perform the index operation if the last\n// operation that has changed the document has the specified sequence number.\nfunc (r *BulkIndexRequest) IfSeqNo(ifSeqNo int64) *BulkIndexRequest {\n\tr.ifSeqNo = &ifSeqNo\n\treturn r\n}\n\n// IfPrimaryTerm indicates to only perform the index operation if the\n// last operation that has changed the document has the specified primary term.\nfunc (r *BulkIndexRequest) IfPrimaryTerm(ifPrimaryTerm int64) *BulkIndexRequest {\n\tr.ifPrimaryTerm = &ifPrimaryTerm\n\treturn r\n}\n\n// String returns the on-wire representation of the index request,\n// concatenated as a single string.\nfunc (r *BulkIndexRequest) String() string {\n\tlines, err := r.Source()\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"error: %v\", err)\n\t}\n\treturn strings.Join(lines, \"\\n\")\n}\n\n// Source returns the on-wire representation of the index request,\n// split into an action-and-meta-data line and an (optional) source line.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for details.\nfunc (r *BulkIndexRequest) Source() ([]string, error) {\n\t// { \"index\" : { \"_index\" : \"test\", \"_type\" : \"type1\", \"_id\" : \"1\" } }\n\t// { \"field1\" : \"value1\" }\n\n\tif r.source != nil {\n\t\treturn r.source, nil\n\t}\n\n\tlines := make([]string, 2)\n\n\t// \"index\" ...\n\tindexCommand := bulkIndexRequestCommandOp{\n\t\tIndex:           r.index,\n\t\tType:            r.typ,\n\t\tId:              r.id,\n\t\tRouting:         r.routing,\n\t\tParent:          r.parent,\n\t\tVersion:         r.version,\n\t\tVersionType:     r.versionType,\n\t\tRetryOnConflict: r.retryOnConflict,\n\t\tPipeline:        r.pipeline,\n\t\tIfSeqNo:         r.ifSeqNo,\n\t\tIfPrimaryTerm:   r.ifPrimaryTerm,\n\t}\n\tcommand := bulkIndexRequestCommand{\n\t\tr.opType: indexCommand,\n\t}\n\n\tvar err error\n\tvar body []byte\n\tif r.useEasyJSON {\n\t\t// easyjson\n\t\tbody, err = command.MarshalJSON()\n\t} else {\n\t\t// encoding/json\n\t\tbody, err = json.Marshal(command)\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlines[0] = string(body)\n\n\t// \"field1\" ...\n\tif r.doc != nil {\n\t\tswitch t := r.doc.(type) {\n\t\tdefault:\n\t\t\tbody, err := json.Marshal(r.doc)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tlines[1] = string(body)\n\t\tcase json.RawMessage:\n\t\t\tlines[1] = string(t)\n\t\tcase *json.RawMessage:\n\t\t\tlines[1] = string(*t)\n\t\tcase string:\n\t\t\tlines[1] = t\n\t\tcase *string:\n\t\t\tlines[1] = *t\n\t\t}\n\t} else {\n\t\tlines[1] = \"{}\"\n\t}\n\n\tr.source = lines\n\treturn lines, nil\n}\n"
  },
  {
    "path": "bulk_index_request_easyjson.go",
    "content": "// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.\n\npackage elastic\n\nimport (\n\tjson \"encoding/json\"\n\teasyjson \"github.com/mailru/easyjson\"\n\tjlexer \"github.com/mailru/easyjson/jlexer\"\n\tjwriter \"github.com/mailru/easyjson/jwriter\"\n)\n\n// suppress unused package warning\nvar (\n\t_ *json.RawMessage\n\t_ *jlexer.Lexer\n\t_ *jwriter.Writer\n\t_ easyjson.Marshaler\n)\n\nfunc easyjson9de0fcbfDecodeGithubComOlivereElasticV7(in *jlexer.Lexer, out *bulkIndexRequestCommandOp) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tif isTopLevel {\n\t\t\tin.Consumed()\n\t\t}\n\t\tin.Skip()\n\t\treturn\n\t}\n\tin.Delim('{')\n\tfor !in.IsDelim('}') {\n\t\tkey := in.UnsafeFieldName(false)\n\t\tin.WantColon()\n\t\tif in.IsNull() {\n\t\t\tin.Skip()\n\t\t\tin.WantComma()\n\t\t\tcontinue\n\t\t}\n\t\tswitch key {\n\t\tcase \"_index\":\n\t\t\tout.Index = string(in.String())\n\t\tcase \"_id\":\n\t\t\tout.Id = string(in.String())\n\t\tcase \"_type\":\n\t\t\tout.Type = string(in.String())\n\t\tcase \"parent\":\n\t\t\tout.Parent = string(in.String())\n\t\tcase \"retry_on_conflict\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.RetryOnConflict = nil\n\t\t\t} else {\n\t\t\t\tif out.RetryOnConflict == nil {\n\t\t\t\t\tout.RetryOnConflict = new(int)\n\t\t\t\t}\n\t\t\t\t*out.RetryOnConflict = int(in.Int())\n\t\t\t}\n\t\tcase \"routing\":\n\t\t\tout.Routing = string(in.String())\n\t\tcase \"version\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.Version = nil\n\t\t\t} else {\n\t\t\t\tif out.Version == nil {\n\t\t\t\t\tout.Version = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.Version = int64(in.Int64())\n\t\t\t}\n\t\tcase \"version_type\":\n\t\t\tout.VersionType = string(in.String())\n\t\tcase \"pipeline\":\n\t\t\tout.Pipeline = string(in.String())\n\t\tcase \"if_seq_no\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.IfSeqNo = nil\n\t\t\t} else {\n\t\t\t\tif out.IfSeqNo == nil {\n\t\t\t\t\tout.IfSeqNo = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.IfSeqNo = int64(in.Int64())\n\t\t\t}\n\t\tcase \"if_primary_term\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.IfPrimaryTerm = nil\n\t\t\t} else {\n\t\t\t\tif out.IfPrimaryTerm == nil {\n\t\t\t\t\tout.IfPrimaryTerm = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.IfPrimaryTerm = int64(in.Int64())\n\t\t\t}\n\t\tdefault:\n\t\t\tin.SkipRecursive()\n\t\t}\n\t\tin.WantComma()\n\t}\n\tin.Delim('}')\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson9de0fcbfEncodeGithubComOlivereElasticV7(out *jwriter.Writer, in bulkIndexRequestCommandOp) {\n\tout.RawByte('{')\n\tfirst := true\n\t_ = first\n\tif in.Index != \"\" {\n\t\tconst prefix string = \",\\\"_index\\\":\"\n\t\tfirst = false\n\t\tout.RawString(prefix[1:])\n\t\tout.String(string(in.Index))\n\t}\n\tif in.Id != \"\" {\n\t\tconst prefix string = \",\\\"_id\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Id))\n\t}\n\tif in.Type != \"\" {\n\t\tconst prefix string = \",\\\"_type\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Type))\n\t}\n\tif in.Parent != \"\" {\n\t\tconst prefix string = \",\\\"parent\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Parent))\n\t}\n\tif in.RetryOnConflict != nil {\n\t\tconst prefix string = \",\\\"retry_on_conflict\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int(int(*in.RetryOnConflict))\n\t}\n\tif in.Routing != \"\" {\n\t\tconst prefix string = \",\\\"routing\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Routing))\n\t}\n\tif in.Version != nil {\n\t\tconst prefix string = \",\\\"version\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.Version))\n\t}\n\tif in.VersionType != \"\" {\n\t\tconst prefix string = \",\\\"version_type\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.VersionType))\n\t}\n\tif in.Pipeline != \"\" {\n\t\tconst prefix string = \",\\\"pipeline\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Pipeline))\n\t}\n\tif in.IfSeqNo != nil {\n\t\tconst prefix string = \",\\\"if_seq_no\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.IfSeqNo))\n\t}\n\tif in.IfPrimaryTerm != nil {\n\t\tconst prefix string = \",\\\"if_primary_term\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.IfPrimaryTerm))\n\t}\n\tout.RawByte('}')\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v bulkIndexRequestCommandOp) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson9de0fcbfEncodeGithubComOlivereElasticV7(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v bulkIndexRequestCommandOp) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson9de0fcbfEncodeGithubComOlivereElasticV7(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *bulkIndexRequestCommandOp) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson9de0fcbfDecodeGithubComOlivereElasticV7(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *bulkIndexRequestCommandOp) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson9de0fcbfDecodeGithubComOlivereElasticV7(l, v)\n}\nfunc easyjson9de0fcbfDecodeGithubComOlivereElasticV71(in *jlexer.Lexer, out *bulkIndexRequestCommand) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tin.Skip()\n\t} else {\n\t\tin.Delim('{')\n\t\t*out = make(bulkIndexRequestCommand)\n\t\tfor !in.IsDelim('}') {\n\t\t\tkey := string(in.String())\n\t\t\tin.WantColon()\n\t\t\tvar v1 bulkIndexRequestCommandOp\n\t\t\t(v1).UnmarshalEasyJSON(in)\n\t\t\t(*out)[key] = v1\n\t\t\tin.WantComma()\n\t\t}\n\t\tin.Delim('}')\n\t}\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson9de0fcbfEncodeGithubComOlivereElasticV71(out *jwriter.Writer, in bulkIndexRequestCommand) {\n\tif in == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {\n\t\tout.RawString(`null`)\n\t} else {\n\t\tout.RawByte('{')\n\t\tv2First := true\n\t\tfor v2Name, v2Value := range in {\n\t\t\tif v2First {\n\t\t\t\tv2First = false\n\t\t\t} else {\n\t\t\t\tout.RawByte(',')\n\t\t\t}\n\t\t\tout.String(string(v2Name))\n\t\t\tout.RawByte(':')\n\t\t\t(v2Value).MarshalEasyJSON(out)\n\t\t}\n\t\tout.RawByte('}')\n\t}\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v bulkIndexRequestCommand) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson9de0fcbfEncodeGithubComOlivereElasticV71(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v bulkIndexRequestCommand) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson9de0fcbfEncodeGithubComOlivereElasticV71(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *bulkIndexRequestCommand) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson9de0fcbfDecodeGithubComOlivereElasticV71(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *bulkIndexRequestCommand) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson9de0fcbfDecodeGithubComOlivereElasticV71(l, v)\n}\n"
  },
  {
    "path": "bulk_index_request_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestBulkIndexRequestSerialization(t *testing.T) {\n\ttests := []struct {\n\t\tRequest  BulkableRequest\n\t\tExpected []string\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tRequest: NewBulkIndexRequest().Index(\"index1\").Id(\"1\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"index\":{\"_index\":\"index1\",\"_id\":\"1\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tRequest: NewBulkIndexRequest().OpType(\"create\").Index(\"index1\").Id(\"1\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"create\":{\"_index\":\"index1\",\"_id\":\"1\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tRequest: NewBulkIndexRequest().OpType(\"index\").Index(\"index1\").Id(\"1\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"index\":{\"_index\":\"index1\",\"_id\":\"1\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #3\n\t\t{\n\t\t\tRequest: NewBulkIndexRequest().OpType(\"index\").Index(\"index1\").Id(\"1\").RetryOnConflict(42).\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"index\":{\"_index\":\"index1\",\"_id\":\"1\",\"retry_on_conflict\":42}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #4\n\t\t{\n\t\t\tRequest: NewBulkIndexRequest().OpType(\"index\").Index(\"index1\").Id(\"1\").Pipeline(\"my_pipeline\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"index\":{\"_index\":\"index1\",\"_id\":\"1\",\"pipeline\":\"my_pipeline\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #5\n\t\t{\n\t\t\tRequest: NewBulkIndexRequest().OpType(\"index\").Index(\"index1\").Id(\"1\").\n\t\t\t\tRouting(\"123\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"index\":{\"_index\":\"index1\",\"_id\":\"1\",\"routing\":\"123\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t\t// #6\n\t\t{\n\t\t\tRequest: NewBulkIndexRequest().OpType(\"index\").Index(\"index1\").Type(\"doc\").Id(\"1\").\n\t\t\t\tVersion(0).\n\t\t\t\tVersionType(\"external\").\n\t\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"index\":{\"_index\":\"index1\",\"_id\":\"1\",\"_type\":\"doc\",\"version\":0,\"version_type\":\"external\"}}`,\n\t\t\t\t`{\"user\":\"olivere\",\"message\":\"\",\"retweets\":0,\"created\":\"2014-01-18T23:59:58Z\"}`,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tlines, err := test.Request.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"case #%d: expected no error, got: %v\", i, err)\n\t\t}\n\t\tif lines == nil {\n\t\t\tt.Fatalf(\"case #%d: expected lines, got nil\", i)\n\t\t}\n\t\tif len(lines) != len(test.Expected) {\n\t\t\tt.Fatalf(\"case #%d: expected %d lines, got %d\", i, len(test.Expected), len(lines))\n\t\t}\n\t\tfor j, line := range lines {\n\t\t\tif line != test.Expected[j] {\n\t\t\t\tt.Errorf(\"case #%d: expected line #%d to be %s, got: %s\", i, j, test.Expected[j], line)\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar bulkIndexRequestSerializationResult string\n\nfunc BenchmarkBulkIndexRequestSerialization(b *testing.B) {\n\tb.Run(\"stdlib\", func(b *testing.B) {\n\t\tr := NewBulkIndexRequest().Index(testIndexName).Id(\"1\").\n\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)})\n\t\tbenchmarkBulkIndexRequestSerialization(b, r.UseEasyJSON(false))\n\t})\n\tb.Run(\"easyjson\", func(b *testing.B) {\n\t\tr := NewBulkIndexRequest().Index(testIndexName).Id(\"1\").\n\t\t\tDoc(tweet{User: \"olivere\", Created: time.Date(2014, 1, 18, 23, 59, 58, 0, time.UTC)})\n\t\tbenchmarkBulkIndexRequestSerialization(b, r.UseEasyJSON(true))\n\t})\n}\n\nfunc benchmarkBulkIndexRequestSerialization(b *testing.B, r *BulkIndexRequest) {\n\tvar s string\n\tfor n := 0; n < b.N; n++ {\n\t\ts = r.String()\n\t\tr.source = nil // Don't let caching spoil the benchmark\n\t}\n\tbulkIndexRequestSerializationResult = s // ensure the compiler doesn't optimize\n\tb.ReportAllocs()\n}\n"
  },
  {
    "path": "bulk_processor.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n)\n\nvar (\n\t// ErrBulkItemRetry is returned in BulkProcessor from a worker when\n\t// a response item needs to be retried.\n\tErrBulkItemRetry = errors.New(\"elastic: uncommitted bulk response items\")\n\n\tdefaultRetryItemStatusCodes = []int{408, 429, 503, 507}\n)\n\n// BulkProcessorService allows to easily process bulk requests. It allows setting\n// policies when to flush new bulk requests, e.g. based on a number of actions,\n// on the size of the actions, and/or to flush periodically. It also allows\n// to control the number of concurrent bulk requests allowed to be executed\n// in parallel.\n//\n// BulkProcessorService, by default, commits either every 1000 requests or when the\n// (estimated) size of the bulk requests exceeds 5 MB. However, it does not\n// commit periodically. BulkProcessorService also does retry by default, using\n// an exponential backoff algorithm. It also will automatically re-enqueue items\n// returned with a status of 408, 429, 503 or 507. You can change this\n// behavior with RetryItemStatusCodes.\n//\n// The caller is responsible for setting the index and type on every\n// bulk request added to BulkProcessorService.\n//\n// BulkProcessorService takes ideas from the BulkProcessor of the\n// Elasticsearch Java API as documented in\n// https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs-bulk-processor.html.\ntype BulkProcessorService struct {\n\tc                    *Client\n\tbeforeFn             BulkBeforeFunc\n\tafterFn              BulkAfterFunc\n\tname                 string        // name of processor\n\tnumWorkers           int           // # of workers (>= 1)\n\tbulkActions          int           // # of requests after which to commit\n\tbulkSize             int           // # of bytes after which to commit\n\tflushInterval        time.Duration // periodic flush interval\n\twantStats            bool          // indicates whether to gather statistics\n\tbackoff              Backoff       // a custom Backoff to use for errors\n\tretryItemStatusCodes []int         // array of status codes for bulk response line items that may be retried\n}\n\n// NewBulkProcessorService creates a new BulkProcessorService.\nfunc NewBulkProcessorService(client *Client) *BulkProcessorService {\n\treturn &BulkProcessorService{\n\t\tc:           client,\n\t\tnumWorkers:  1,\n\t\tbulkActions: 1000,\n\t\tbulkSize:    5 << 20, // 5 MB\n\t\tbackoff: NewExponentialBackoff(\n\t\t\ttime.Duration(200)*time.Millisecond,\n\t\t\ttime.Duration(10000)*time.Millisecond,\n\t\t),\n\t\tretryItemStatusCodes: defaultRetryItemStatusCodes,\n\t}\n}\n\n// BulkBeforeFunc defines the signature of callbacks that are executed\n// before a commit to Elasticsearch.\ntype BulkBeforeFunc func(executionId int64, requests []BulkableRequest)\n\n// BulkAfterFunc defines the signature of callbacks that are executed\n// after a commit to Elasticsearch. The err parameter signals an error.\ntype BulkAfterFunc func(executionId int64, requests []BulkableRequest, response *BulkResponse, err error)\n\n// Before specifies a function to be executed before bulk requests get committed\n// to Elasticsearch.\nfunc (s *BulkProcessorService) Before(fn BulkBeforeFunc) *BulkProcessorService {\n\ts.beforeFn = fn\n\treturn s\n}\n\n// After specifies a function to be executed when bulk requests have been\n// committed to Elasticsearch. The After callback executes both when the\n// commit was successful as well as on failures.\nfunc (s *BulkProcessorService) After(fn BulkAfterFunc) *BulkProcessorService {\n\ts.afterFn = fn\n\treturn s\n}\n\n// Name is an optional name to identify this bulk processor.\nfunc (s *BulkProcessorService) Name(name string) *BulkProcessorService {\n\ts.name = name\n\treturn s\n}\n\n// Workers is the number of concurrent workers allowed to be\n// executed. Defaults to 1 and must be greater or equal to 1.\nfunc (s *BulkProcessorService) Workers(num int) *BulkProcessorService {\n\ts.numWorkers = num\n\treturn s\n}\n\n// BulkActions specifies when to flush based on the number of actions\n// currently added. Defaults to 1000 and can be set to -1 to be disabled.\nfunc (s *BulkProcessorService) BulkActions(bulkActions int) *BulkProcessorService {\n\ts.bulkActions = bulkActions\n\treturn s\n}\n\n// BulkSize specifies when to flush based on the size (in bytes) of the actions\n// currently added. Defaults to 5 MB and can be set to -1 to be disabled.\nfunc (s *BulkProcessorService) BulkSize(bulkSize int) *BulkProcessorService {\n\ts.bulkSize = bulkSize\n\treturn s\n}\n\n// FlushInterval specifies when to flush at the end of the given interval.\n// This is disabled by default. If you want the bulk processor to\n// operate completely asynchronously, set both BulkActions and BulkSize to\n// -1 and set the FlushInterval to a meaningful interval.\nfunc (s *BulkProcessorService) FlushInterval(interval time.Duration) *BulkProcessorService {\n\ts.flushInterval = interval\n\treturn s\n}\n\n// Stats tells bulk processor to gather stats while running.\n// Use Stats to return the stats. This is disabled by default.\nfunc (s *BulkProcessorService) Stats(wantStats bool) *BulkProcessorService {\n\ts.wantStats = wantStats\n\treturn s\n}\n\n// Backoff sets the backoff strategy to use for errors.\nfunc (s *BulkProcessorService) Backoff(backoff Backoff) *BulkProcessorService {\n\ts.backoff = backoff\n\treturn s\n}\n\n// RetryItemStatusCodes sets an array of status codes that indicate that a bulk\n// response line item should be retried.\nfunc (s *BulkProcessorService) RetryItemStatusCodes(retryItemStatusCodes ...int) *BulkProcessorService {\n\ts.retryItemStatusCodes = retryItemStatusCodes\n\treturn s\n}\n\n// Do creates a new BulkProcessor and starts it.\n// Consider the BulkProcessor as a running instance that accepts bulk requests\n// and commits them to Elasticsearch, spreading the work across one or more\n// workers.\n//\n// You can interoperate with the BulkProcessor returned by Do, e.g. Start and\n// Stop (or Close) it.\n//\n// Context is an optional context that is passed into the bulk request\n// service calls. In contrast to other operations, this context is used in\n// a long running process. You could use it to pass e.g. loggers, but you\n// shouldn't use it for cancellation.\n//\n// Calling Do several times returns new BulkProcessors. You probably don't\n// want to do this. BulkProcessorService implements just a builder pattern.\nfunc (s *BulkProcessorService) Do(ctx context.Context) (*BulkProcessor, error) {\n\n\tretryItemStatusCodes := make(map[int]struct{})\n\tfor _, code := range s.retryItemStatusCodes {\n\t\tretryItemStatusCodes[code] = struct{}{}\n\t}\n\n\tp := newBulkProcessor(\n\t\ts.c,\n\t\ts.beforeFn,\n\t\ts.afterFn,\n\t\ts.name,\n\t\ts.numWorkers,\n\t\ts.bulkActions,\n\t\ts.bulkSize,\n\t\ts.flushInterval,\n\t\ts.wantStats,\n\t\ts.backoff,\n\t\tretryItemStatusCodes)\n\n\terr := p.Start(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn p, nil\n}\n\n// -- Bulk Processor Statistics --\n\n// BulkProcessorStats contains various statistics of a bulk processor\n// while it is running. Use the Stats func to return it while running.\ntype BulkProcessorStats struct {\n\tFlushed   int64 // number of times the flush interval has been invoked\n\tCommitted int64 // # of times workers committed bulk requests\n\tIndexed   int64 // # of requests indexed\n\tCreated   int64 // # of requests that ES reported as creates (201)\n\tUpdated   int64 // # of requests that ES reported as updates\n\tDeleted   int64 // # of requests that ES reported as deletes\n\tSucceeded int64 // # of requests that ES reported as successful\n\tFailed    int64 // # of requests that ES reported as failed\n\n\tWorkers []*BulkProcessorWorkerStats // stats for each worker\n}\n\n// BulkProcessorWorkerStats represents per-worker statistics.\ntype BulkProcessorWorkerStats struct {\n\tQueued       int64         // # of requests queued in this worker\n\tLastDuration time.Duration // duration of last commit\n}\n\n// newBulkProcessorStats initializes and returns a BulkProcessorStats struct.\nfunc newBulkProcessorStats(workers int) *BulkProcessorStats {\n\tstats := &BulkProcessorStats{\n\t\tWorkers: make([]*BulkProcessorWorkerStats, workers),\n\t}\n\tfor i := 0; i < workers; i++ {\n\t\tstats.Workers[i] = &BulkProcessorWorkerStats{}\n\t}\n\treturn stats\n}\n\nfunc (st *BulkProcessorStats) dup() *BulkProcessorStats {\n\tdst := new(BulkProcessorStats)\n\tdst.Flushed = st.Flushed\n\tdst.Committed = st.Committed\n\tdst.Indexed = st.Indexed\n\tdst.Created = st.Created\n\tdst.Updated = st.Updated\n\tdst.Deleted = st.Deleted\n\tdst.Succeeded = st.Succeeded\n\tdst.Failed = st.Failed\n\tfor _, src := range st.Workers {\n\t\tdst.Workers = append(dst.Workers, src.dup())\n\t}\n\treturn dst\n}\n\nfunc (st *BulkProcessorWorkerStats) dup() *BulkProcessorWorkerStats {\n\tdst := new(BulkProcessorWorkerStats)\n\tdst.Queued = st.Queued\n\tdst.LastDuration = st.LastDuration\n\treturn dst\n}\n\n// -- Bulk Processor --\n\n// BulkProcessor encapsulates a task that accepts bulk requests and\n// orchestrates committing them to Elasticsearch via one or more workers.\n//\n// BulkProcessor is returned by setting up a BulkProcessorService and\n// calling the Do method.\ntype BulkProcessor struct {\n\tc                    *Client\n\tbeforeFn             BulkBeforeFunc\n\tafterFn              BulkAfterFunc\n\tname                 string\n\tbulkActions          int\n\tbulkSize             int\n\tnumWorkers           int\n\texecutionId          int64\n\trequestsC            chan BulkableRequest\n\tworkerWg             sync.WaitGroup\n\tworkers              []*bulkWorker\n\tflushInterval        time.Duration\n\tflusherStopC         chan struct{}\n\twantStats            bool\n\tretryItemStatusCodes map[int]struct{}\n\tbackoff              Backoff\n\n\tstartedMu sync.Mutex // guards the following block\n\tstarted   bool\n\n\tstatsMu sync.Mutex // guards the following block\n\tstats   *BulkProcessorStats\n\n\tstopReconnC chan struct{} // channel to signal stop reconnection attempts\n}\n\nfunc newBulkProcessor(\n\tclient *Client,\n\tbeforeFn BulkBeforeFunc,\n\tafterFn BulkAfterFunc,\n\tname string,\n\tnumWorkers int,\n\tbulkActions int,\n\tbulkSize int,\n\tflushInterval time.Duration,\n\twantStats bool,\n\tbackoff Backoff,\n\tretryItemStatusCodes map[int]struct{}) *BulkProcessor {\n\treturn &BulkProcessor{\n\t\tc:                    client,\n\t\tbeforeFn:             beforeFn,\n\t\tafterFn:              afterFn,\n\t\tname:                 name,\n\t\tnumWorkers:           numWorkers,\n\t\tbulkActions:          bulkActions,\n\t\tbulkSize:             bulkSize,\n\t\tflushInterval:        flushInterval,\n\t\twantStats:            wantStats,\n\t\tretryItemStatusCodes: retryItemStatusCodes,\n\t\tbackoff:              backoff,\n\t}\n}\n\n// Start starts the bulk processor. If the processor is already started,\n// nil is returned.\nfunc (p *BulkProcessor) Start(ctx context.Context) error {\n\tp.startedMu.Lock()\n\tdefer p.startedMu.Unlock()\n\n\tif p.started {\n\t\treturn nil\n\t}\n\n\t// We must have at least one worker.\n\tif p.numWorkers < 1 {\n\t\tp.numWorkers = 1\n\t}\n\n\tp.requestsC = make(chan BulkableRequest)\n\tp.executionId = 0\n\tp.stats = newBulkProcessorStats(p.numWorkers)\n\tp.stopReconnC = make(chan struct{})\n\n\t// Create and start up workers.\n\tp.workers = make([]*bulkWorker, p.numWorkers)\n\tfor i := 0; i < p.numWorkers; i++ {\n\t\tp.workerWg.Add(1)\n\t\tp.workers[i] = newBulkWorker(p, i)\n\t\tgo p.workers[i].work(ctx)\n\t}\n\n\t// Start the ticker for flush (if enabled)\n\tif int64(p.flushInterval) > 0 {\n\t\tp.flusherStopC = make(chan struct{})\n\t\tgo p.flusher(p.flushInterval)\n\t}\n\n\tp.started = true\n\n\treturn nil\n}\n\n// Stop is an alias for Close.\nfunc (p *BulkProcessor) Stop() error {\n\treturn p.Close()\n}\n\n// Close stops the bulk processor previously started with Do.\n// If it is already stopped, this is a no-op and nil is returned.\n//\n// By implementing Close, BulkProcessor implements the io.Closer interface.\nfunc (p *BulkProcessor) Close() error {\n\tp.startedMu.Lock()\n\tdefer p.startedMu.Unlock()\n\n\t// Already stopped? Do nothing.\n\tif !p.started {\n\t\treturn nil\n\t}\n\n\t// Tell connection checkers to stop\n\tif p.stopReconnC != nil {\n\t\tclose(p.stopReconnC)\n\t\tp.stopReconnC = nil\n\t}\n\n\t// Stop flusher (if enabled)\n\tif p.flusherStopC != nil {\n\t\tp.flusherStopC <- struct{}{}\n\t\t<-p.flusherStopC\n\t\tclose(p.flusherStopC)\n\t\tp.flusherStopC = nil\n\t}\n\n\t// Stop all workers.\n\tclose(p.requestsC)\n\tp.workerWg.Wait()\n\n\tp.started = false\n\n\treturn nil\n}\n\n// Stats returns the latest bulk processor statistics.\n// Collecting stats must be enabled first by calling Stats(true) on\n// the service that created this processor.\nfunc (p *BulkProcessor) Stats() BulkProcessorStats {\n\tp.statsMu.Lock()\n\tdefer p.statsMu.Unlock()\n\treturn *p.stats.dup()\n}\n\n// Add adds a single request to commit by the BulkProcessorService.\n//\n// The caller is responsible for setting the index and type on the request.\nfunc (p *BulkProcessor) Add(request BulkableRequest) {\n\tp.requestsC <- request\n}\n\n// Flush manually asks all workers to commit their outstanding requests.\n// It returns only when all workers acknowledge completion.\nfunc (p *BulkProcessor) Flush() error {\n\tp.statsMu.Lock()\n\tp.stats.Flushed++\n\tp.statsMu.Unlock()\n\n\tfor _, w := range p.workers {\n\t\tw.flushC <- struct{}{}\n\t\t<-w.flushAckC // wait for completion\n\t}\n\treturn nil\n}\n\n// flusher is a single goroutine that periodically asks all workers to\n// commit their outstanding bulk requests. It is only started if\n// FlushInterval is greater than 0.\nfunc (p *BulkProcessor) flusher(interval time.Duration) {\n\tticker := time.NewTicker(interval)\n\tdefer ticker.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase <-ticker.C: // Periodic flush\n\t\t\tp.Flush() // TODO swallow errors here?\n\n\t\tcase <-p.flusherStopC:\n\t\t\tp.flusherStopC <- struct{}{}\n\t\t\treturn\n\t\t}\n\t}\n}\n\n// -- Bulk Worker --\n\n// bulkWorker encapsulates a single worker, running in a goroutine,\n// receiving bulk requests and eventually committing them to Elasticsearch.\n// It is strongly bound to a BulkProcessor.\ntype bulkWorker struct {\n\tp           *BulkProcessor\n\ti           int\n\tbulkActions int\n\tbulkSize    int\n\tservice     *BulkService\n\tflushC      chan struct{}\n\tflushAckC   chan struct{}\n}\n\n// newBulkWorker creates a new bulkWorker instance.\nfunc newBulkWorker(p *BulkProcessor, i int) *bulkWorker {\n\treturn &bulkWorker{\n\t\tp:           p,\n\t\ti:           i,\n\t\tbulkActions: p.bulkActions,\n\t\tbulkSize:    p.bulkSize,\n\t\tservice:     NewBulkService(p.c),\n\t\tflushC:      make(chan struct{}),\n\t\tflushAckC:   make(chan struct{}),\n\t}\n}\n\n// work waits for bulk requests and manual flush calls on the respective\n// channels and is invoked as a goroutine when the bulk processor is started.\nfunc (w *bulkWorker) work(ctx context.Context) {\n\tdefer func() {\n\t\tw.p.workerWg.Done()\n\t\tclose(w.flushAckC)\n\t\tclose(w.flushC)\n\t}()\n\n\tvar stop bool\n\tfor !stop {\n\t\tvar err error\n\t\tselect {\n\t\tcase req, open := <-w.p.requestsC:\n\t\t\tif open {\n\t\t\t\t// Received a new request\n\t\t\t\tif _, err = req.Source(); err == nil {\n\t\t\t\t\tw.service.Add(req)\n\t\t\t\t\tif w.commitRequired() {\n\t\t\t\t\t\terr = w.commit(ctx)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Channel closed: Stop.\n\t\t\t\tstop = true\n\t\t\t\tif w.service.NumberOfActions() > 0 {\n\t\t\t\t\terr = w.commit(ctx)\n\t\t\t\t}\n\t\t\t}\n\n\t\tcase <-w.flushC:\n\t\t\t// Commit outstanding requests\n\t\t\tif w.service.NumberOfActions() > 0 {\n\t\t\t\terr = w.commit(ctx)\n\t\t\t}\n\t\t\tw.flushAckC <- struct{}{}\n\t\t}\n\t\tif err != nil {\n\t\t\tw.p.c.errorf(\"elastic: bulk processor %q was unable to perform work: %v\", w.p.name, err)\n\t\t\tif !stop {\n\t\t\t\twaitForActive := func() {\n\t\t\t\t\t// Add back pressure to prevent Add calls from filling up the request queue\n\t\t\t\t\tready := make(chan struct{})\n\t\t\t\t\tgo w.waitForActiveConnection(ready)\n\t\t\t\t\t<-ready\n\t\t\t\t}\n\t\t\t\tif _, ok := err.(net.Error); ok {\n\t\t\t\t\twaitForActive()\n\t\t\t\t} else if IsConnErr(err) {\n\t\t\t\t\twaitForActive()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// commit commits the bulk requests in the given service,\n// invoking callbacks as specified.\nfunc (w *bulkWorker) commit(ctx context.Context) error {\n\tvar res *BulkResponse\n\n\t// commitFunc will commit bulk requests and, on failure, be retried\n\t// via exponential backoff\n\tcommitFunc := func() error {\n\t\tvar err error\n\t\t// Save requests because they will be reset in service.Do\n\t\treqs := w.service.requests\n\t\tres, err = w.service.Do(ctx)\n\t\tif err == nil {\n\t\t\t// Overall bulk request was OK.  But each bulk response item also has a status\n\t\t\tif w.p.retryItemStatusCodes != nil && len(w.p.retryItemStatusCodes) > 0 {\n\t\t\t\t// Check res.Items since some might be soft failures\n\t\t\t\tif res.Items != nil && res.Errors {\n\t\t\t\t\t// res.Items will be 1 to 1 with reqs in same order\n\t\t\t\t\tfor i, item := range res.Items {\n\t\t\t\t\t\tfor _, result := range item {\n\t\t\t\t\t\t\tif _, found := w.p.retryItemStatusCodes[result.Status]; found {\n\t\t\t\t\t\t\t\tw.service.Add(reqs[i])\n\t\t\t\t\t\t\t\tif err == nil {\n\t\t\t\t\t\t\t\t\terr = ErrBulkItemRetry\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn err\n\t}\n\t// notifyFunc will be called if retry fails\n\tnotifyFunc := func(err error) {\n\t\tw.p.c.errorf(\"elastic: bulk processor %q failed but may retry: %v\", w.p.name, err)\n\t}\n\n\tid := atomic.AddInt64(&w.p.executionId, 1)\n\n\t// Update # documents in queue before eventual retries\n\tw.p.statsMu.Lock()\n\tif w.p.wantStats {\n\t\tw.p.stats.Workers[w.i].Queued = int64(len(w.service.requests))\n\t}\n\tw.p.statsMu.Unlock()\n\n\t// Save requests because they will be reset in commitFunc\n\treqs := w.service.requests\n\n\t// Invoke before callback\n\tif w.p.beforeFn != nil {\n\t\tw.p.beforeFn(id, reqs)\n\t}\n\n\t// Commit bulk requests\n\terr := RetryNotify(commitFunc, w.p.backoff, notifyFunc)\n\tw.updateStats(res)\n\tif err != nil {\n\t\tw.p.c.errorf(\"elastic: bulk processor %q failed: %v\", w.p.name, err)\n\t}\n\n\t// Invoke after callback\n\tif w.p.afterFn != nil {\n\t\tw.p.afterFn(id, reqs, res, err)\n\t}\n\n\treturn err\n}\n\nfunc (w *bulkWorker) waitForActiveConnection(ready chan<- struct{}) {\n\tdefer close(ready)\n\n\tt := time.NewTicker(5 * time.Second)\n\tdefer t.Stop()\n\n\tclient := w.p.c\n\tstopReconnC := w.p.stopReconnC\n\tw.p.c.errorf(\"elastic: bulk processor %q is waiting for an active connection\", w.p.name)\n\n\t// loop until a health check finds at least 1 active connection or the reconnection channel is closed\n\tfor {\n\t\tselect {\n\t\tcase _, ok := <-stopReconnC:\n\t\t\tif !ok {\n\t\t\t\tw.p.c.errorf(\"elastic: bulk processor %q active connection check interrupted\", w.p.name)\n\t\t\t\treturn\n\t\t\t}\n\t\tcase <-t.C:\n\t\t\tclient.healthcheck(context.Background(), 3*time.Second, true)\n\t\t\tif client.mustActiveConn() == nil {\n\t\t\t\t// found an active connection\n\t\t\t\t// exit and signal done to the WaitGroup\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc (w *bulkWorker) updateStats(res *BulkResponse) {\n\t// Update stats\n\tif res != nil {\n\t\tw.p.statsMu.Lock()\n\t\tif w.p.wantStats {\n\t\t\tw.p.stats.Committed++\n\t\t\tif res != nil {\n\t\t\t\tw.p.stats.Indexed += int64(len(res.Indexed()))\n\t\t\t\tw.p.stats.Created += int64(len(res.Created()))\n\t\t\t\tw.p.stats.Updated += int64(len(res.Updated()))\n\t\t\t\tw.p.stats.Deleted += int64(len(res.Deleted()))\n\t\t\t\tw.p.stats.Succeeded += int64(len(res.Succeeded()))\n\t\t\t\tw.p.stats.Failed += int64(len(res.Failed()))\n\t\t\t}\n\t\t\tw.p.stats.Workers[w.i].Queued = int64(len(w.service.requests))\n\t\t\tw.p.stats.Workers[w.i].LastDuration = time.Duration(int64(res.Took)) * time.Millisecond\n\t\t}\n\t\tw.p.statsMu.Unlock()\n\t}\n}\n\n// commitRequired returns true if the service has to commit its\n// bulk requests. This can be either because the number of actions\n// or the estimated size in bytes is larger than specified in the\n// BulkProcessorService.\nfunc (w *bulkWorker) commitRequired() bool {\n\tif w.bulkActions >= 0 && w.service.NumberOfActions() >= w.bulkActions {\n\t\treturn true\n\t}\n\tif w.bulkSize >= 0 && w.service.EstimatedSizeInBytes() >= int64(w.bulkSize) {\n\t\treturn true\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "bulk_processor_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"reflect\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestBulkProcessorDefaults(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t, SetHealthcheckTimeoutStartup(15*time.Second), SetSnifferTimeoutStartup(15*time.Second))\n\n\tp := client.BulkProcessor()\n\tif p == nil {\n\t\tt.Fatalf(\"expected BulkProcessorService; got: %v\", p)\n\t}\n\tif got, want := p.name, \"\"; got != want {\n\t\tt.Errorf(\"expected %q; got: %q\", want, got)\n\t}\n\tif got, want := p.numWorkers, 1; got != want {\n\t\tt.Errorf(\"expected %d; got: %d\", want, got)\n\t}\n\tif got, want := p.bulkActions, 1000; got != want {\n\t\tt.Errorf(\"expected %d; got: %d\", want, got)\n\t}\n\tif got, want := p.bulkSize, 5*1024*1024; got != want {\n\t\tt.Errorf(\"expected %d; got: %d\", want, got)\n\t}\n\tif got, want := p.flushInterval, time.Duration(0); got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := p.wantStats, false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := p.retryItemStatusCodes, defaultRetryItemStatusCodes; !reflect.DeepEqual(got, want) {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif p.backoff == nil {\n\t\tt.Fatalf(\"expected non-nil backoff; got: %v\", p.backoff)\n\t}\n}\n\nfunc TestBulkProcessorCommitOnBulkActions(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t, SetHealthcheckTimeoutStartup(15*time.Second), SetSnifferTimeoutStartup(15*time.Second))\n\n\ttestBulkProcessor(t,\n\t\t10000,\n\t\tclient.BulkProcessor().\n\t\t\tName(\"Actions-1\").\n\t\t\tWorkers(1).\n\t\t\tBulkActions(100).\n\t\t\tBulkSize(-1),\n\t)\n\n\ttestBulkProcessor(t,\n\t\t10000,\n\t\tclient.BulkProcessor().\n\t\t\tName(\"Actions-2\").\n\t\t\tWorkers(2).\n\t\t\tBulkActions(100).\n\t\t\tBulkSize(-1),\n\t)\n}\n\nfunc TestBulkProcessorCommitOnBulkSize(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t, SetHealthcheckTimeoutStartup(15*time.Second), SetSnifferTimeoutStartup(15*time.Second))\n\n\ttestBulkProcessor(t,\n\t\t10000,\n\t\tclient.BulkProcessor().\n\t\t\tName(\"Size-1\").\n\t\t\tWorkers(1).\n\t\t\tBulkActions(-1).\n\t\t\tBulkSize(64*1024),\n\t)\n\n\ttestBulkProcessor(t,\n\t\t10000,\n\t\tclient.BulkProcessor().\n\t\t\tName(\"Size-2\").\n\t\t\tWorkers(2).\n\t\t\tBulkActions(-1).\n\t\t\tBulkSize(64*1024),\n\t)\n}\n\nfunc TestBulkProcessorBasedOnFlushInterval(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t, SetHealthcheckTimeoutStartup(15*time.Second), SetSnifferTimeoutStartup(15*time.Second))\n\n\tvar beforeRequests int64\n\tvar befores int64\n\tvar afters int64\n\tvar failures int64\n\tvar afterRequests int64\n\n\tbeforeFn := func(executionId int64, requests []BulkableRequest) {\n\t\tatomic.AddInt64(&beforeRequests, int64(len(requests)))\n\t\tatomic.AddInt64(&befores, 1)\n\t}\n\tafterFn := func(executionId int64, requests []BulkableRequest, response *BulkResponse, err error) {\n\t\tatomic.AddInt64(&afters, 1)\n\t\tif err != nil {\n\t\t\tatomic.AddInt64(&failures, 1)\n\t\t}\n\t\tatomic.AddInt64(&afterRequests, int64(len(requests)))\n\t}\n\n\tsvc := client.BulkProcessor().\n\t\tName(\"FlushInterval-1\").\n\t\tWorkers(2).\n\t\tBulkActions(-1).\n\t\tBulkSize(-1).\n\t\tFlushInterval(1 * time.Second).\n\t\tBefore(beforeFn).\n\t\tAfter(afterFn)\n\n\tp, err := svc.Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tconst numDocs = 1000 // low-enough number that flush should be invoked\n\n\tfor i := 1; i <= numDocs; i++ {\n\t\ttweet := tweet{User: \"olivere\", Message: fmt.Sprintf(\"%d. %s\", i, randomString(rand.Intn(64)))}\n\t\trequest := NewBulkIndexRequest().Index(testIndexName).Id(fmt.Sprintf(\"%d\", i)).Doc(tweet)\n\t\tp.Add(request)\n\t}\n\n\t// Should flush at least once\n\ttime.Sleep(2 * time.Second)\n\n\terr = p.Close()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif p.stats.Flushed == 0 {\n\t\tt.Errorf(\"expected at least 1 flush; got: %d\", p.stats.Flushed)\n\t}\n\tif got, want := beforeRequests, int64(numDocs); got != want {\n\t\tt.Errorf(\"expected %d requests to before callback; got: %d\", want, got)\n\t}\n\tif got, want := afterRequests, int64(numDocs); got != want {\n\t\tt.Errorf(\"expected %d requests to after callback; got: %d\", want, got)\n\t}\n\tif befores == 0 {\n\t\tt.Error(\"expected at least 1 call to before callback\")\n\t}\n\tif afters == 0 {\n\t\tt.Error(\"expected at least 1 call to after callback\")\n\t}\n\tif failures != 0 {\n\t\tt.Errorf(\"expected 0 calls to failure callback; got: %d\", failures)\n\t}\n\n\t// Check number of documents that were bulk indexed\n\t_, err = p.c.Refresh(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcount, err := p.c.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != int64(numDocs) {\n\t\tt.Fatalf(\"expected %d documents; got: %d\", numDocs, count)\n\t}\n}\n\nfunc TestBulkProcessorClose(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t, SetHealthcheckTimeoutStartup(15*time.Second), SetSnifferTimeoutStartup(15*time.Second))\n\n\tvar beforeRequests int64\n\tvar befores int64\n\tvar afters int64\n\tvar failures int64\n\tvar afterRequests int64\n\n\tbeforeFn := func(executionId int64, requests []BulkableRequest) {\n\t\tatomic.AddInt64(&beforeRequests, int64(len(requests)))\n\t\tatomic.AddInt64(&befores, 1)\n\t}\n\tafterFn := func(executionId int64, requests []BulkableRequest, response *BulkResponse, err error) {\n\t\tatomic.AddInt64(&afters, 1)\n\t\tif err != nil {\n\t\t\tatomic.AddInt64(&failures, 1)\n\t\t}\n\t\tatomic.AddInt64(&afterRequests, int64(len(requests)))\n\t}\n\n\tp, err := client.BulkProcessor().\n\t\tName(\"FlushInterval-1\").\n\t\tWorkers(2).\n\t\tBulkActions(-1).\n\t\tBulkSize(-1).\n\t\tFlushInterval(30 * time.Second). // 30 seconds to flush\n\t\tBefore(beforeFn).After(afterFn).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tconst numDocs = 1000 // low-enough number that flush should be invoked\n\n\tfor i := 1; i <= numDocs; i++ {\n\t\ttweet := tweet{User: \"olivere\", Message: fmt.Sprintf(\"%d. %s\", i, randomString(rand.Intn(64)))}\n\t\trequest := NewBulkIndexRequest().Index(testIndexName).Id(fmt.Sprintf(\"%d\", i)).Doc(tweet)\n\t\tp.Add(request)\n\t}\n\n\t// Should not flush because 30s > 1s\n\ttime.Sleep(1 * time.Second)\n\n\t// Close should flush\n\terr = p.Close()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif p.stats.Flushed != 0 {\n\t\tt.Errorf(\"expected no flush; got: %d\", p.stats.Flushed)\n\t}\n\tif got, want := beforeRequests, int64(numDocs); got != want {\n\t\tt.Errorf(\"expected %d requests to before callback; got: %d\", want, got)\n\t}\n\tif got, want := afterRequests, int64(numDocs); got != want {\n\t\tt.Errorf(\"expected %d requests to after callback; got: %d\", want, got)\n\t}\n\tif befores == 0 {\n\t\tt.Error(\"expected at least 1 call to before callback\")\n\t}\n\tif afters == 0 {\n\t\tt.Error(\"expected at least 1 call to after callback\")\n\t}\n\tif failures != 0 {\n\t\tt.Errorf(\"expected 0 calls to failure callback; got: %d\", failures)\n\t}\n\n\t// Check number of documents that were bulk indexed\n\t_, err = p.c.Refresh(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcount, err := p.c.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != int64(numDocs) {\n\t\tt.Fatalf(\"expected %d documents; got: %d\", numDocs, count)\n\t}\n}\n\nfunc TestBulkProcessorFlush(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t, SetHealthcheckTimeoutStartup(15*time.Second), SetSnifferTimeoutStartup(15*time.Second))\n\n\tp, err := client.BulkProcessor().\n\t\tName(\"ManualFlush\").\n\t\tWorkers(10).\n\t\tBulkActions(-1).\n\t\tBulkSize(-1).\n\t\tFlushInterval(30 * time.Second). // 30 seconds to flush\n\t\tStats(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tconst numDocs = 100\n\n\tfor i := 1; i <= numDocs; i++ {\n\t\ttweet := tweet{User: \"olivere\", Message: fmt.Sprintf(\"%d. %s\", i, randomString(rand.Intn(64)))}\n\t\trequest := NewBulkIndexRequest().Index(testIndexName).Id(fmt.Sprintf(\"%d\", i)).Doc(tweet)\n\t\tp.Add(request)\n\t}\n\n\t// Should not flush because 30s > 1s\n\ttime.Sleep(1 * time.Second)\n\n\t// No flush yet\n\tstats := p.Stats()\n\tif stats.Flushed != 0 {\n\t\tt.Errorf(\"expected no flush; got: %d\", p.stats.Flushed)\n\t}\n\n\t// Manual flush\n\terr = p.Flush()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttime.Sleep(1 * time.Second)\n\n\t// Now flushed\n\tstats = p.Stats()\n\tif got, want := p.stats.Flushed, int64(1); got != want {\n\t\tt.Errorf(\"expected %d flush; got: %d\", want, got)\n\t}\n\n\t// Close should not start another flush\n\terr = p.Close()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Still 1 flush\n\tstats = p.Stats()\n\tif got, want := p.stats.Flushed, int64(1); got != want {\n\t\tt.Errorf(\"expected %d flush; got: %d\", want, got)\n\t}\n\n\t// Check number of documents that were bulk indexed\n\t_, err = p.c.Refresh(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcount, err := p.c.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != int64(numDocs) {\n\t\tt.Fatalf(\"expected %d documents; got: %d\", numDocs, count)\n\t}\n}\n\n// -- Helper --\n\nfunc testBulkProcessor(t *testing.T, numDocs int, svc *BulkProcessorService) {\n\tvar beforeRequests int64\n\tvar befores int64\n\tvar afters int64\n\tvar failures int64\n\tvar afterRequests int64\n\n\tbeforeFn := func(executionId int64, requests []BulkableRequest) {\n\t\tatomic.AddInt64(&beforeRequests, int64(len(requests)))\n\t\tatomic.AddInt64(&befores, 1)\n\t}\n\tafterFn := func(executionId int64, requests []BulkableRequest, response *BulkResponse, err error) {\n\t\tatomic.AddInt64(&afters, 1)\n\t\tif err != nil {\n\t\t\tatomic.AddInt64(&failures, 1)\n\t\t}\n\t\tatomic.AddInt64(&afterRequests, int64(len(requests)))\n\t}\n\n\tp, err := svc.Before(beforeFn).After(afterFn).Stats(true).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tfor i := 1; i <= numDocs; i++ {\n\t\ttweet := tweet{User: \"olivere\", Message: fmt.Sprintf(\"%07d. %s\", i, randomString(1+rand.Intn(63)))}\n\t\trequest := NewBulkIndexRequest().Index(testIndexName).Id(fmt.Sprintf(\"%d\", i)).Doc(tweet)\n\t\tp.Add(request)\n\t}\n\n\terr = p.Close()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tstats := p.Stats()\n\n\tif stats.Flushed != 0 {\n\t\tt.Errorf(\"expected no flush; got: %d\", stats.Flushed)\n\t}\n\tif stats.Committed <= 0 {\n\t\tt.Errorf(\"expected committed > %d; got: %d\", 0, stats.Committed)\n\t}\n\tif got, want := stats.Indexed, int64(numDocs); got != want {\n\t\tt.Errorf(\"expected indexed = %d; got: %d\", want, got)\n\t}\n\tif got, want := stats.Created, int64(0); got != want {\n\t\tt.Errorf(\"expected created = %d; got: %d\", want, got)\n\t}\n\tif got, want := stats.Updated, int64(0); got != want {\n\t\tt.Errorf(\"expected updated = %d; got: %d\", want, got)\n\t}\n\tif got, want := stats.Deleted, int64(0); got != want {\n\t\tt.Errorf(\"expected deleted = %d; got: %d\", want, got)\n\t}\n\tif got, want := stats.Succeeded, int64(numDocs); got != want {\n\t\tt.Errorf(\"expected succeeded = %d; got: %d\", want, got)\n\t}\n\tif got, want := stats.Failed, int64(0); got != want {\n\t\tt.Errorf(\"expected failed = %d; got: %d\", want, got)\n\t}\n\tif got, want := beforeRequests, int64(numDocs); got != want {\n\t\tt.Errorf(\"expected %d requests to before callback; got: %d\", want, got)\n\t}\n\tif got, want := afterRequests, int64(numDocs); got != want {\n\t\tt.Errorf(\"expected %d requests to after callback; got: %d\", want, got)\n\t}\n\tif befores == 0 {\n\t\tt.Error(\"expected at least 1 call to before callback\")\n\t}\n\tif afters == 0 {\n\t\tt.Error(\"expected at least 1 call to after callback\")\n\t}\n\tif failures != 0 {\n\t\tt.Errorf(\"expected 0 calls to failure callback; got: %d\", failures)\n\t}\n\n\t// Check number of documents that were bulk indexed\n\t_, err = p.c.Refresh(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcount, err := p.c.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != int64(numDocs) {\n\t\tt.Fatalf(\"expected %d documents; got: %d\", numDocs, count)\n\t}\n}\n"
  },
  {
    "path": "bulk_request.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"fmt\"\n)\n\n// -- Bulkable request (index/update/delete) --\n\n// BulkableRequest is a generic interface to bulkable requests.\ntype BulkableRequest interface {\n\tfmt.Stringer\n\tSource() ([]string, error)\n}\n"
  },
  {
    "path": "bulk_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n)\n\nfunc TestBulk(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"sandrae\", Message: \"Dancing all night long. Yeah.\"}\n\n\tindex1Req := NewBulkIndexRequest().Index(testIndexName).Id(\"1\").Doc(tweet1)\n\tindex2Req := NewBulkIndexRequest().Index(testIndexName).Id(\"2\").Doc(tweet2)\n\tdelete1Req := NewBulkDeleteRequest().Index(testIndexName).Id(\"1\")\n\n\tbulkRequest := client.Bulk()\n\tbulkRequest = bulkRequest.Add(index1Req)\n\tbulkRequest = bulkRequest.Add(index2Req)\n\tbulkRequest = bulkRequest.Add(delete1Req)\n\n\tif bulkRequest.NumberOfActions() != 3 {\n\t\tt.Errorf(\"expected bulkRequest.NumberOfActions %d; got %d\", 3, bulkRequest.NumberOfActions())\n\t}\n\n\tbulkResponse, err := bulkRequest.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif bulkResponse == nil {\n\t\tt.Errorf(\"expected bulkResponse to be != nil; got nil\")\n\t}\n\n\tif bulkRequest.NumberOfActions() != 0 {\n\t\tt.Errorf(\"expected bulkRequest.NumberOfActions %d; got %d\", 0, bulkRequest.NumberOfActions())\n\t}\n\n\t// Document with Id=\"1\" should not exist\n\texists, err := client.Exists().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif exists {\n\t\tt.Errorf(\"expected exists %v; got %v\", false, exists)\n\t}\n\n\t// Document with Id=\"2\" should exist\n\texists, err = client.Exists().Index(testIndexName).Id(\"2\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !exists {\n\t\tt.Errorf(\"expected exists %v; got %v\", true, exists)\n\t}\n\n\t// Update\n\tupdateDoc := struct {\n\t\tRetweets int `json:\"retweets\"`\n\t}{\n\t\t42,\n\t}\n\tupdate1Req := NewBulkUpdateRequest().Index(testIndexName).Id(\"2\").Doc(&updateDoc)\n\tbulkRequest = client.Bulk()\n\tbulkRequest = bulkRequest.Add(update1Req)\n\n\tif bulkRequest.NumberOfActions() != 1 {\n\t\tt.Errorf(\"expected bulkRequest.NumberOfActions %d; got %d\", 1, bulkRequest.NumberOfActions())\n\t}\n\n\tbulkResponse, err = bulkRequest.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif bulkResponse == nil {\n\t\tt.Errorf(\"expected bulkResponse to be != nil; got nil\")\n\t}\n\n\tif bulkRequest.NumberOfActions() != 0 {\n\t\tt.Errorf(\"expected bulkRequest.NumberOfActions %d; got %d\", 0, bulkRequest.NumberOfActions())\n\t}\n\n\t// Document with Id=\"1\" should have a retweets count of 42\n\tdoc, err := client.Get().Index(testIndexName).Id(\"2\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif doc == nil {\n\t\tt.Fatal(\"expected doc to be != nil; got nil\")\n\t}\n\tif !doc.Found {\n\t\tt.Fatalf(\"expected doc to be found; got found = %v\", doc.Found)\n\t}\n\tif doc.Source == nil {\n\t\tt.Fatal(\"expected doc source to be != nil; got nil\")\n\t}\n\tvar updatedTweet tweet\n\terr = json.Unmarshal(doc.Source, &updatedTweet)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif updatedTweet.Retweets != 42 {\n\t\tt.Errorf(\"expected updated tweet retweets = %v; got %v\", 42, updatedTweet.Retweets)\n\t}\n\n\t// Update with script\n\tupdate2Req := NewBulkUpdateRequest().Index(testIndexName).Id(\"2\").\n\t\tRetryOnConflict(3).\n\t\tScript(NewScript(\"ctx._source.retweets += params.v\").Param(\"v\", 1))\n\tbulkRequest = client.Bulk()\n\tbulkRequest = bulkRequest.Add(update2Req)\n\tif bulkRequest.NumberOfActions() != 1 {\n\t\tt.Errorf(\"expected bulkRequest.NumberOfActions %d; got %d\", 1, bulkRequest.NumberOfActions())\n\t}\n\tbulkResponse, err = bulkRequest.Refresh(\"wait_for\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif bulkResponse == nil {\n\t\tt.Errorf(\"expected bulkResponse to be != nil; got nil\")\n\t}\n\n\tif bulkRequest.NumberOfActions() != 0 {\n\t\tt.Errorf(\"expected bulkRequest.NumberOfActions %d; got %d\", 0, bulkRequest.NumberOfActions())\n\t}\n\n\t// Document with Id=\"1\" should have a retweets count of 43\n\tdoc, err = client.Get().Index(testIndexName).Id(\"2\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif doc == nil {\n\t\tt.Fatal(\"expected doc to be != nil; got nil\")\n\t}\n\tif !doc.Found {\n\t\tt.Fatalf(\"expected doc to be found; got found = %v\", doc.Found)\n\t}\n\tif doc.Source == nil {\n\t\tt.Fatal(\"expected doc source to be != nil; got nil\")\n\t}\n\terr = json.Unmarshal(doc.Source, &updatedTweet)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif updatedTweet.Retweets != 43 {\n\t\tt.Errorf(\"expected updated tweet retweets = %v; got %v\", 43, updatedTweet.Retweets)\n\t}\n}\n\nfunc TestBulkWithIndexSetOnClient(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"sandrae\", Message: \"Dancing all night long. Yeah.\"}\n\n\tindex1Req := NewBulkIndexRequest().Index(testIndexName).Id(\"1\").Doc(tweet1).Routing(\"1\")\n\tindex2Req := NewBulkIndexRequest().Index(testIndexName).Id(\"2\").Doc(tweet2)\n\tdelete1Req := NewBulkDeleteRequest().Index(testIndexName).Id(\"1\")\n\n\tbulkRequest := client.Bulk().Index(testIndexName)\n\tbulkRequest = bulkRequest.Add(index1Req)\n\tbulkRequest = bulkRequest.Add(index2Req)\n\tbulkRequest = bulkRequest.Add(delete1Req)\n\n\tif bulkRequest.NumberOfActions() != 3 {\n\t\tt.Errorf(\"expected bulkRequest.NumberOfActions %d; got %d\", 3, bulkRequest.NumberOfActions())\n\t}\n\n\tbulkResponse, err := bulkRequest.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif bulkResponse == nil {\n\t\tt.Errorf(\"expected bulkResponse to be != nil; got nil\")\n\t}\n\n\t// Document with Id=\"1\" should not exist\n\texists, err := client.Exists().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif exists {\n\t\tt.Errorf(\"expected exists %v; got %v\", false, exists)\n\t}\n\n\t// Document with Id=\"2\" should exist\n\texists, err = client.Exists().Index(testIndexName).Id(\"2\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !exists {\n\t\tt.Errorf(\"expected exists %v; got %v\", true, exists)\n\t}\n}\n\nfunc TestBulkIndexDeleteUpdate(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\t//client := setupTestClientAndCreateIndexAndLog(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"sandrae\", Message: \"Dancing all night long. Yeah.\"}\n\n\tindex1Req := NewBulkIndexRequest().Index(testIndexName).Id(\"1\").Doc(tweet1)\n\tindex2Req := NewBulkIndexRequest().OpType(\"create\").Index(testIndexName).Id(\"2\").Doc(tweet2)\n\tdelete1Req := NewBulkDeleteRequest().Index(testIndexName).Id(\"1\")\n\tupdate2Req := NewBulkUpdateRequest().Index(testIndexName).Id(\"2\").\n\t\tReturnSource(true).\n\t\tDoc(struct {\n\t\t\tRetweets int `json:\"retweets\"`\n\t\t}{\n\t\t\tRetweets: 42,\n\t\t})\n\n\tbulkRequest := client.Bulk()\n\tbulkRequest = bulkRequest.Add(index1Req)\n\tbulkRequest = bulkRequest.Add(index2Req)\n\tbulkRequest = bulkRequest.Add(delete1Req)\n\tbulkRequest = bulkRequest.Add(update2Req)\n\n\tif bulkRequest.NumberOfActions() != 4 {\n\t\tt.Errorf(\"expected bulkRequest.NumberOfActions %d; got %d\", 4, bulkRequest.NumberOfActions())\n\t}\n\n\texpected := `{\"index\":{\"_index\":\"` + testIndexName + `\",\"_id\":\"1\"}}\n{\"user\":\"olivere\",\"message\":\"Welcome to Golang and Elasticsearch.\",\"retweets\":0,\"created\":\"0001-01-01T00:00:00Z\"}\n{\"create\":{\"_index\":\"` + testIndexName + `\",\"_id\":\"2\"}}\n{\"user\":\"sandrae\",\"message\":\"Dancing all night long. Yeah.\",\"retweets\":0,\"created\":\"0001-01-01T00:00:00Z\"}\n{\"delete\":{\"_index\":\"` + testIndexName + `\",\"_id\":\"1\"}}\n{\"update\":{\"_index\":\"` + testIndexName + `\",\"_id\":\"2\"}}\n{\"doc\":{\"retweets\":42},\"_source\":true}\n`\n\tgot, err := bulkRequest.bodyAsString()\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error, got: %v\", err)\n\t}\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\ngot:\\n%s\", expected, got)\n\t}\n\n\t// Run the bulk request\n\tbulkResponse, err := bulkRequest.Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif bulkResponse == nil {\n\t\tt.Fatal(\"expected bulkResponse to be != nil; got nil\")\n\t}\n\tif bulkResponse.Took == 0 {\n\t\tt.Errorf(\"expected took to be > 0; got %d\", bulkResponse.Took)\n\t}\n\tif bulkResponse.Errors {\n\t\tt.Errorf(\"expected errors to be %v; got %v\", false, bulkResponse.Errors)\n\t}\n\tif len(bulkResponse.Items) != 4 {\n\t\tt.Fatalf(\"expected 4 result items; got %d\", len(bulkResponse.Items))\n\t}\n\n\t// Indexed actions\n\tindexed := bulkResponse.Indexed()\n\tif indexed == nil {\n\t\tt.Fatal(\"expected indexed to be != nil; got nil\")\n\t}\n\tif len(indexed) != 1 {\n\t\tt.Fatalf(\"expected len(indexed) == %d; got %d\", 1, len(indexed))\n\t}\n\tif indexed[0].Id != \"1\" {\n\t\tt.Errorf(\"expected indexed[0].Id == %s; got %s\", \"1\", indexed[0].Id)\n\t}\n\tif indexed[0].Status != 201 {\n\t\tt.Errorf(\"expected indexed[0].Status == %d; got %d\", 201, indexed[0].Status)\n\t}\n\n\t// Created actions\n\tcreated := bulkResponse.Created()\n\tif created == nil {\n\t\tt.Fatal(\"expected created to be != nil; got nil\")\n\t}\n\tif len(created) != 1 {\n\t\tt.Fatalf(\"expected len(created) == %d; got %d\", 1, len(created))\n\t}\n\tif created[0].Id != \"2\" {\n\t\tt.Errorf(\"expected created[0].Id == %s; got %s\", \"2\", created[0].Id)\n\t}\n\tif created[0].Status != 201 {\n\t\tt.Errorf(\"expected created[0].Status == %d; got %d\", 201, created[0].Status)\n\t}\n\tif want, have := \"created\", created[0].Result; want != have {\n\t\tt.Errorf(\"expected created[0].Result == %q; got %q\", want, have)\n\t}\n\n\t// Deleted actions\n\tdeleted := bulkResponse.Deleted()\n\tif deleted == nil {\n\t\tt.Fatal(\"expected deleted to be != nil; got nil\")\n\t}\n\tif len(deleted) != 1 {\n\t\tt.Fatalf(\"expected len(deleted) == %d; got %d\", 1, len(deleted))\n\t}\n\tif deleted[0].Id != \"1\" {\n\t\tt.Errorf(\"expected deleted[0].Id == %s; got %s\", \"1\", deleted[0].Id)\n\t}\n\tif deleted[0].Status != 200 {\n\t\tt.Errorf(\"expected deleted[0].Status == %d; got %d\", 200, deleted[0].Status)\n\t}\n\tif want, have := \"deleted\", deleted[0].Result; want != have {\n\t\tt.Errorf(\"expected deleted[0].Result == %q; got %q\", want, have)\n\t}\n\n\t// Updated actions\n\tupdated := bulkResponse.Updated()\n\tif updated == nil {\n\t\tt.Fatal(\"expected updated to be != nil; got nil\")\n\t}\n\tif len(updated) != 1 {\n\t\tt.Fatalf(\"expected len(updated) == %d; got %d\", 1, len(updated))\n\t}\n\tif updated[0].Id != \"2\" {\n\t\tt.Errorf(\"expected updated[0].Id == %s; got %s\", \"2\", updated[0].Id)\n\t}\n\tif updated[0].Status != 200 {\n\t\tt.Errorf(\"expected updated[0].Status == %d; got %d\", 200, updated[0].Status)\n\t}\n\tif updated[0].Version != 2 {\n\t\tt.Errorf(\"expected updated[0].Version == %d; got %d\", 2, updated[0].Version)\n\t}\n\tif want, have := \"updated\", updated[0].Result; want != have {\n\t\tt.Errorf(\"expected updated[0].Result == %q; got %q\", want, have)\n\t}\n\tif updated[0].GetResult == nil {\n\t\tt.Fatalf(\"expected updated[0].GetResult to be != nil; got nil\")\n\t}\n\tif updated[0].GetResult.Source == nil {\n\t\tt.Fatalf(\"expected updated[0].GetResult.Source to be != nil; got nil\")\n\t}\n\tif want, have := true, updated[0].GetResult.Found; want != have {\n\t\tt.Fatalf(\"expected updated[0].GetResult.Found to be != %v; got %v\", want, have)\n\t}\n\tvar doc tweet\n\tif err := json.Unmarshal(updated[0].GetResult.Source, &doc); err != nil {\n\t\tt.Fatalf(\"expected to unmarshal updated[0].GetResult.Source; got %v\", err)\n\t}\n\tif want, have := 42, doc.Retweets; want != have {\n\t\tt.Fatalf(\"expected updated tweet to have Retweets = %v; got %v\", want, have)\n\t}\n\n\t// Succeeded actions\n\tsucceeded := bulkResponse.Succeeded()\n\tif succeeded == nil {\n\t\tt.Fatal(\"expected succeeded to be != nil; got nil\")\n\t}\n\tif len(succeeded) != 4 {\n\t\tt.Fatalf(\"expected len(succeeded) == %d; got %d\", 4, len(succeeded))\n\t}\n\n\t// ById\n\tid1Results := bulkResponse.ById(\"1\")\n\tif id1Results == nil {\n\t\tt.Fatal(\"expected id1Results to be != nil; got nil\")\n\t}\n\tif len(id1Results) != 2 {\n\t\tt.Fatalf(\"expected len(id1Results) == %d; got %d\", 2, len(id1Results))\n\t}\n\tif id1Results[0].Id != \"1\" {\n\t\tt.Errorf(\"expected id1Results[0].Id == %s; got %s\", \"1\", id1Results[0].Id)\n\t}\n\tif id1Results[0].Status != 201 {\n\t\tt.Errorf(\"expected id1Results[0].Status == %d; got %d\", 201, id1Results[0].Status)\n\t}\n\tif id1Results[0].Version != 1 {\n\t\tt.Errorf(\"expected id1Results[0].Version == %d; got %d\", 1, id1Results[0].Version)\n\t}\n\tif id1Results[1].Id != \"1\" {\n\t\tt.Errorf(\"expected id1Results[1].Id == %s; got %s\", \"1\", id1Results[1].Id)\n\t}\n\tif id1Results[1].Status != 200 {\n\t\tt.Errorf(\"expected id1Results[1].Status == %d; got %d\", 200, id1Results[1].Status)\n\t}\n\tif id1Results[1].Version != 2 {\n\t\tt.Errorf(\"expected id1Results[1].Version == %d; got %d\", 2, id1Results[1].Version)\n\t}\n}\n\nfunc TestBulkOnReadOnlyIndex(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\t//client := setupTestClientAndCreateIndexAndLog(t)\n\n\t// Change index to read-only\n\t{\n\t\t_, err := client.IndexPutSettings(testIndexName).\n\t\t\tBodyString(`{\n\t\t\t\t\"index\": {\n\t\t\t\t\t\"blocks\": {\n\t\t\t\t\t\t\"read_only_allow_delete\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}`).Pretty(true).Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"unable to set index into read-only mode: %v\", err)\n\t\t}\n\t}\n\n\t// Index something\n\ttweet := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\tbulk := client.Bulk().Add(\n\t\tNewBulkIndexRequest().Index(testIndexName).Id(\"1\").Doc(tweet),\n\t)\n\tresp, err := bulk.Pretty(true).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif resp == nil {\n\t\tt.Fatal(\"expected response to be != nil; got nil\")\n\t}\n\tif !resp.Errors {\n\t\tt.Fatal(\"expected response errors being set to true\")\n\t}\n\tif len(resp.Items) != 1 {\n\t\tt.Fatal(\"expected response with 1 item\")\n\t}\n\tif want, have := http.StatusTooManyRequests, resp.ById(\"1\")[0].Status; want != have {\n\t\tt.Fatal(\"expected HTTP status code 200\")\n\t}\n}\n\nfunc TestFailedBulkRequests(t *testing.T) {\n\tjs := `{\n  \"took\" : 2,\n  \"errors\" : true,\n  \"items\" : [ {\n    \"index\" : {\n      \"_index\" : \"elastic-test\",\n      \"_type\" : \"_doc\",\n      \"_id\" : \"1\",\n      \"_version\" : 1,\n      \"status\" : 201\n    }\n  }, {\n    \"create\" : {\n      \"_index\" : \"elastic-test\",\n      \"_type\" : \"_doc\",\n      \"_id\" : \"2\",\n      \"_version\" : 1,\n      \"status\" : 423,\n      \"error\" : {\n      \t\"type\":\"routing_missing_exception\",\n      \t\"reason\":\"routing is required for [elastic-test2]/[comment]/[1]\"\n      }\n    }\n  }, {\n    \"delete\" : {\n      \"_index\" : \"elastic-test\",\n      \"_type\" : \"_doc\",\n      \"_id\" : \"1\",\n      \"_version\" : 2,\n      \"status\" : 404,\n      \"found\" : false\n    }\n  }, {\n    \"update\" : {\n      \"_index\" : \"elastic-test\",\n      \"_type\" : \"_doc\",\n      \"_id\" : \"2\",\n      \"_version\" : 2,\n      \"status\" : 200\n    }\n  } ]\n}`\n\n\tvar resp BulkResponse\n\terr := json.Unmarshal([]byte(js), &resp)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfailed := resp.Failed()\n\tif len(failed) != 2 {\n\t\tt.Errorf(\"expected %d failed items; got: %d\", 2, len(failed))\n\t}\n}\n\nfunc TestBulkEstimatedSizeInBytes(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"sandrae\", Message: \"Dancing all night long. Yeah.\"}\n\n\tindex1Req := NewBulkIndexRequest().Index(testIndexName).Id(\"1\").Doc(tweet1)\n\tindex2Req := NewBulkIndexRequest().OpType(\"create\").Index(testIndexName).Id(\"2\").Doc(tweet2)\n\tdelete1Req := NewBulkDeleteRequest().Index(testIndexName).Id(\"1\")\n\tupdate2Req := NewBulkUpdateRequest().Index(testIndexName).Id(\"2\").\n\t\tDoc(struct {\n\t\t\tRetweets int `json:\"retweets\"`\n\t\t}{\n\t\t\tRetweets: 42,\n\t\t})\n\n\tbulkRequest := client.Bulk()\n\tbulkRequest = bulkRequest.Add(index1Req)\n\tbulkRequest = bulkRequest.Add(index2Req)\n\tbulkRequest = bulkRequest.Add(delete1Req)\n\tbulkRequest = bulkRequest.Add(update2Req)\n\n\tif bulkRequest.NumberOfActions() != 4 {\n\t\tt.Errorf(\"expected bulkRequest.NumberOfActions %d; got %d\", 4, bulkRequest.NumberOfActions())\n\t}\n\n\t// The estimated size of the bulk request in bytes must be at least\n\t// the length of the body request.\n\traw, err := bulkRequest.bodyAsString()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\trawlen := int64(len([]byte(raw)))\n\n\tif got, want := bulkRequest.EstimatedSizeInBytes(), rawlen; got < want {\n\t\tt.Errorf(\"expected an EstimatedSizeInBytes = %d; got: %v\", want, got)\n\t}\n\n\t// Reset should also reset the calculated estimated byte size\n\tbulkRequest.Reset()\n\n\tif got, want := bulkRequest.EstimatedSizeInBytes(), int64(0); got != want {\n\t\tt.Errorf(\"expected an EstimatedSizeInBytes = %d; got: %v\", want, got)\n\t}\n}\n\nfunc TestBulkEstimateSizeInBytesLength(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\ts := client.Bulk()\n\tr := NewBulkDeleteRequest().Index(testIndexName).Id(\"1\")\n\ts = s.Add(r)\n\tif got, want := s.estimateSizeInBytes(r), int64(1+len(r.String())); got != want {\n\t\tt.Fatalf(\"expected %d; got: %d\", want, got)\n\t}\n}\n\nfunc TestBulkContentType(t *testing.T) {\n\tvar header http.Header\n\tts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\theader = r.Header\n\t\tfmt.Fprintln(w, `{}`)\n\t}))\n\tdefer ts.Close()\n\n\tclient, err := NewSimpleClient(SetURL(ts.URL))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tindexReq := NewBulkIndexRequest().Index(testIndexName).Id(\"1\").Doc(tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"})\n\tif _, err := client.Bulk().Add(indexReq).Do(context.Background()); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif header == nil {\n\t\tt.Fatalf(\"expected header, got %v\", header)\n\t}\n\tif want, have := \"application/x-ndjson\", header.Get(\"Content-Type\"); want != have {\n\t\tt.Fatalf(\"Content-Type: want %q, have %q\", want, have)\n\t}\n}\n\n// -- Benchmarks --\n\nvar benchmarkBulkEstimatedSizeInBytes int64\n\nfunc BenchmarkBulkEstimatedSizeInBytesWith1Request(b *testing.B) {\n\tclient := setupTestClientAndCreateIndex(b)\n\ts := client.Bulk()\n\tvar result int64\n\tfor n := 0; n < b.N; n++ {\n\t\ts = s.Add(NewBulkIndexRequest().Index(testIndexName).Id(\"1\").Doc(struct{ A string }{\"1\"}))\n\t\ts = s.Add(NewBulkUpdateRequest().Index(testIndexName).Id(\"1\").Doc(struct{ A string }{\"2\"}))\n\t\ts = s.Add(NewBulkDeleteRequest().Index(testIndexName).Id(\"1\"))\n\t\tresult = s.EstimatedSizeInBytes()\n\t\ts.Reset()\n\t}\n\tb.ReportAllocs()\n\tbenchmarkBulkEstimatedSizeInBytes = result // ensure the compiler doesn't optimize\n}\n\nfunc BenchmarkBulkEstimatedSizeInBytesWith100Requests(b *testing.B) {\n\tclient := setupTestClientAndCreateIndex(b)\n\ts := client.Bulk()\n\tvar result int64\n\tfor n := 0; n < b.N; n++ {\n\t\tfor i := 0; i < 100; i++ {\n\t\t\ts = s.Add(NewBulkIndexRequest().Index(testIndexName).Id(\"1\").Doc(struct{ A string }{\"1\"}))\n\t\t\ts = s.Add(NewBulkUpdateRequest().Index(testIndexName).Id(\"1\").Doc(struct{ A string }{\"2\"}))\n\t\t\ts = s.Add(NewBulkDeleteRequest().Index(testIndexName).Id(\"1\"))\n\t\t}\n\t\tresult = s.EstimatedSizeInBytes()\n\t\ts.Reset()\n\t}\n\tb.ReportAllocs()\n\tbenchmarkBulkEstimatedSizeInBytes = result // ensure the compiler doesn't optimize\n}\n\nfunc BenchmarkBulkAllocs(b *testing.B) {\n\tb.Run(\"1000 docs with 64 byte\", func(b *testing.B) { benchmarkBulkAllocs(b, 64, 1000) })\n\tb.Run(\"1000 docs with 1 KiB\", func(b *testing.B) { benchmarkBulkAllocs(b, 1024, 1000) })\n\tb.Run(\"1000 docs with 4 KiB\", func(b *testing.B) { benchmarkBulkAllocs(b, 4096, 1000) })\n\tb.Run(\"1000 docs with 16 KiB\", func(b *testing.B) { benchmarkBulkAllocs(b, 16*1024, 1000) })\n\tb.Run(\"1000 docs with 64 KiB\", func(b *testing.B) { benchmarkBulkAllocs(b, 64*1024, 1000) })\n\tb.Run(\"1000 docs with 256 KiB\", func(b *testing.B) { benchmarkBulkAllocs(b, 256*1024, 1000) })\n\tb.Run(\"1000 docs with 1 MiB\", func(b *testing.B) { benchmarkBulkAllocs(b, 1024*1024, 1000) })\n}\n\nconst (\n\tcharset = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-\"\n)\n\nfunc benchmarkBulkAllocs(b *testing.B, size, num int) {\n\tbuf := make([]byte, size)\n\tfor i := range buf {\n\t\tbuf[i] = charset[rand.Intn(len(charset))]\n\t}\n\n\ts := &BulkService{}\n\tn := 0\n\tfor {\n\t\tn++\n\t\ts = s.Add(NewBulkIndexRequest().Index(\"test\").Id(\"1\").Doc(struct {\n\t\t\tS string `json:\"s\"`\n\t\t}{\n\t\t\tS: string(buf),\n\t\t}))\n\t\tif n >= num {\n\t\t\tbreak\n\t\t}\n\t}\n\tfor i := 0; i < b.N; i++ {\n\t\ts.bodyAsString()\n\t}\n\tb.ReportAllocs()\n}\n"
  },
  {
    "path": "bulk_update_request.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n//go:generate easyjson bulk_update_request.go\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// BulkUpdateRequest is a request to update a document in Elasticsearch.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for details.\ntype BulkUpdateRequest struct {\n\tBulkableRequest\n\tindex string\n\ttyp   string\n\tid    string\n\n\trouting         string\n\tparent          string\n\tscript          *Script\n\tscriptedUpsert  *bool\n\tversion         int64  // default is MATCH_ANY\n\tversionType     string // default is \"internal\"\n\tretryOnConflict *int\n\tupsert          interface{}\n\tdocAsUpsert     *bool\n\tdetectNoop      *bool\n\tdoc             interface{}\n\treturnSource    *bool\n\tifSeqNo         *int64\n\tifPrimaryTerm   *int64\n\n\tsource []string\n\n\tuseEasyJSON bool\n}\n\n//easyjson:json\ntype bulkUpdateRequestCommand map[string]bulkUpdateRequestCommandOp\n\n//easyjson:json\ntype bulkUpdateRequestCommandOp struct {\n\tIndex  string `json:\"_index,omitempty\"`\n\tType   string `json:\"_type,omitempty\"`\n\tId     string `json:\"_id,omitempty\"`\n\tParent string `json:\"parent,omitempty\"`\n\t// RetryOnConflict is \"_retry_on_conflict\" for 6.0 and \"retry_on_conflict\" for 6.1+.\n\tRetryOnConflict *int   `json:\"retry_on_conflict,omitempty\"`\n\tRouting         string `json:\"routing,omitempty\"`\n\tVersion         int64  `json:\"version,omitempty\"`\n\tVersionType     string `json:\"version_type,omitempty\"`\n\tIfSeqNo         *int64 `json:\"if_seq_no,omitempty\"`\n\tIfPrimaryTerm   *int64 `json:\"if_primary_term,omitempty\"`\n}\n\n//easyjson:json\ntype bulkUpdateRequestCommandData struct {\n\tDetectNoop     *bool       `json:\"detect_noop,omitempty\"`\n\tDoc            interface{} `json:\"doc,omitempty\"`\n\tDocAsUpsert    *bool       `json:\"doc_as_upsert,omitempty\"`\n\tScript         interface{} `json:\"script,omitempty\"`\n\tScriptedUpsert *bool       `json:\"scripted_upsert,omitempty\"`\n\tUpsert         interface{} `json:\"upsert,omitempty\"`\n\tSource         *bool       `json:\"_source,omitempty\"`\n}\n\n// NewBulkUpdateRequest returns a new BulkUpdateRequest.\nfunc NewBulkUpdateRequest() *BulkUpdateRequest {\n\treturn &BulkUpdateRequest{}\n}\n\n// UseEasyJSON is an experimental setting that enables serialization\n// with github.com/mailru/easyjson, which should in faster serialization\n// time and less allocations, but removed compatibility with encoding/json,\n// usage of unsafe etc. See https://github.com/mailru/easyjson#issues-notes-and-limitations\n// for details. This setting is disabled by default.\nfunc (r *BulkUpdateRequest) UseEasyJSON(enable bool) *BulkUpdateRequest {\n\tr.useEasyJSON = enable\n\treturn r\n}\n\n// Index specifies the Elasticsearch index to use for this update request.\n// If unspecified, the index set on the BulkService will be used.\nfunc (r *BulkUpdateRequest) Index(index string) *BulkUpdateRequest {\n\tr.index = index\n\tr.source = nil\n\treturn r\n}\n\n// Type specifies the Elasticsearch type to use for this update request.\n// If unspecified, the type set on the BulkService will be used.\nfunc (r *BulkUpdateRequest) Type(typ string) *BulkUpdateRequest {\n\tr.typ = typ\n\tr.source = nil\n\treturn r\n}\n\n// Id specifies the identifier of the document to update.\nfunc (r *BulkUpdateRequest) Id(id string) *BulkUpdateRequest {\n\tr.id = id\n\tr.source = nil\n\treturn r\n}\n\n// Routing specifies a routing value for the request.\nfunc (r *BulkUpdateRequest) Routing(routing string) *BulkUpdateRequest {\n\tr.routing = routing\n\tr.source = nil\n\treturn r\n}\n\n// Parent specifies the identifier of the parent document (if available).\nfunc (r *BulkUpdateRequest) Parent(parent string) *BulkUpdateRequest {\n\tr.parent = parent\n\tr.source = nil\n\treturn r\n}\n\n// Script specifies an update script.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html#bulk-update\n// and https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-scripting.html\n// for details.\nfunc (r *BulkUpdateRequest) Script(script *Script) *BulkUpdateRequest {\n\tr.script = script\n\tr.source = nil\n\treturn r\n}\n\n// ScripedUpsert specifies if your script will run regardless of\n// whether the document exists or not.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-update.html#_literal_scripted_upsert_literal\nfunc (r *BulkUpdateRequest) ScriptedUpsert(upsert bool) *BulkUpdateRequest {\n\tr.scriptedUpsert = &upsert\n\tr.source = nil\n\treturn r\n}\n\n// RetryOnConflict specifies how often to retry in case of a version conflict.\nfunc (r *BulkUpdateRequest) RetryOnConflict(retryOnConflict int) *BulkUpdateRequest {\n\tr.retryOnConflict = &retryOnConflict\n\tr.source = nil\n\treturn r\n}\n\n// Version indicates the version of the document as part of an optimistic\n// concurrency model.\nfunc (r *BulkUpdateRequest) Version(version int64) *BulkUpdateRequest {\n\tr.version = version\n\tr.source = nil\n\treturn r\n}\n\n// VersionType can be \"internal\" (default), \"external\", \"external_gte\",\n// or \"external_gt\".\nfunc (r *BulkUpdateRequest) VersionType(versionType string) *BulkUpdateRequest {\n\tr.versionType = versionType\n\tr.source = nil\n\treturn r\n}\n\n// IfSeqNo indicates to only perform the index operation if the last\n// operation that has changed the document has the specified sequence number.\nfunc (r *BulkUpdateRequest) IfSeqNo(ifSeqNo int64) *BulkUpdateRequest {\n\tr.ifSeqNo = &ifSeqNo\n\treturn r\n}\n\n// IfPrimaryTerm indicates to only perform the index operation if the\n// last operation that has changed the document has the specified primary term.\nfunc (r *BulkUpdateRequest) IfPrimaryTerm(ifPrimaryTerm int64) *BulkUpdateRequest {\n\tr.ifPrimaryTerm = &ifPrimaryTerm\n\treturn r\n}\n\n// Doc specifies the updated document.\nfunc (r *BulkUpdateRequest) Doc(doc interface{}) *BulkUpdateRequest {\n\tr.doc = doc\n\tr.source = nil\n\treturn r\n}\n\n// DocAsUpsert indicates whether the contents of Doc should be used as\n// the Upsert value.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-update.html#_literal_doc_as_upsert_literal\n// for details.\nfunc (r *BulkUpdateRequest) DocAsUpsert(docAsUpsert bool) *BulkUpdateRequest {\n\tr.docAsUpsert = &docAsUpsert\n\tr.source = nil\n\treturn r\n}\n\n// DetectNoop specifies whether changes that don't affect the document\n// should be ignored (true) or unignored (false). This is enabled by default\n// in Elasticsearch.\nfunc (r *BulkUpdateRequest) DetectNoop(detectNoop bool) *BulkUpdateRequest {\n\tr.detectNoop = &detectNoop\n\tr.source = nil\n\treturn r\n}\n\n// Upsert specifies the document to use for upserts. It will be used for\n// create if the original document does not exist.\nfunc (r *BulkUpdateRequest) Upsert(doc interface{}) *BulkUpdateRequest {\n\tr.upsert = doc\n\tr.source = nil\n\treturn r\n}\n\n// ReturnSource specifies whether Elasticsearch should return the source\n// after the update. In the request, this responds to the `_source` field.\n// It is false by default.\nfunc (r *BulkUpdateRequest) ReturnSource(source bool) *BulkUpdateRequest {\n\tr.returnSource = &source\n\tr.source = nil\n\treturn r\n}\n\n// String returns the on-wire representation of the update request,\n// concatenated as a single string.\nfunc (r *BulkUpdateRequest) String() string {\n\tlines, err := r.Source()\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"error: %v\", err)\n\t}\n\treturn strings.Join(lines, \"\\n\")\n}\n\n// Source returns the on-wire representation of the update request,\n// split into an action-and-meta-data line and an (optional) source line.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for details.\nfunc (r *BulkUpdateRequest) Source() ([]string, error) {\n\t// { \"update\" : { \"_index\" : \"test\", \"_type\" : \"type1\", \"_id\" : \"1\", ... } }\n\t// { \"doc\" : { \"field1\" : \"value1\", ... } }\n\t// or\n\t// { \"update\" : { \"_index\" : \"test\", \"_type\" : \"type1\", \"_id\" : \"1\", ... } }\n\t// { \"script\" : { ... } }\n\n\tif r.source != nil {\n\t\treturn r.source, nil\n\t}\n\n\tlines := make([]string, 2)\n\n\t// \"update\" ...\n\tupdateCommand := bulkUpdateRequestCommandOp{\n\t\tIndex:           r.index,\n\t\tType:            r.typ,\n\t\tId:              r.id,\n\t\tRouting:         r.routing,\n\t\tParent:          r.parent,\n\t\tVersion:         r.version,\n\t\tVersionType:     r.versionType,\n\t\tRetryOnConflict: r.retryOnConflict,\n\t\tIfSeqNo:         r.ifSeqNo,\n\t\tIfPrimaryTerm:   r.ifPrimaryTerm,\n\t}\n\tcommand := bulkUpdateRequestCommand{\n\t\t\"update\": updateCommand,\n\t}\n\n\tvar err error\n\tvar body []byte\n\tif r.useEasyJSON {\n\t\t// easyjson\n\t\tbody, err = command.MarshalJSON()\n\t} else {\n\t\t// encoding/json\n\t\tbody, err = json.Marshal(command)\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlines[0] = string(body)\n\n\t// 2nd line: {\"doc\" : { ... }} or {\"script\": {...}}\n\tvar doc interface{}\n\tif r.doc != nil {\n\t\t// Automatically serialize strings as raw JSON\n\t\tswitch t := r.doc.(type) {\n\t\tdefault:\n\t\t\tdoc = r.doc\n\t\tcase string:\n\t\t\tif len(t) > 0 {\n\t\t\t\tdoc = json.RawMessage(t)\n\t\t\t}\n\t\tcase *string:\n\t\t\tif t != nil && len(*t) > 0 {\n\t\t\t\tdoc = json.RawMessage(*t)\n\t\t\t}\n\t\t}\n\t}\n\tdata := bulkUpdateRequestCommandData{\n\t\tDocAsUpsert:    r.docAsUpsert,\n\t\tDetectNoop:     r.detectNoop,\n\t\tUpsert:         r.upsert,\n\t\tScriptedUpsert: r.scriptedUpsert,\n\t\tDoc:            doc,\n\t\tSource:         r.returnSource,\n\t}\n\tif r.script != nil {\n\t\tscript, err := r.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdata.Script = script\n\t}\n\n\tif r.useEasyJSON {\n\t\t// easyjson\n\t\tbody, err = data.MarshalJSON()\n\t} else {\n\t\t// encoding/json\n\t\tbody, err = json.Marshal(data)\n\t}\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tlines[1] = string(body)\n\n\tr.source = lines\n\treturn lines, nil\n}\n"
  },
  {
    "path": "bulk_update_request_easyjson.go",
    "content": "// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.\n\npackage elastic\n\nimport (\n\tjson \"encoding/json\"\n\teasyjson \"github.com/mailru/easyjson\"\n\tjlexer \"github.com/mailru/easyjson/jlexer\"\n\tjwriter \"github.com/mailru/easyjson/jwriter\"\n)\n\n// suppress unused package warning\nvar (\n\t_ *json.RawMessage\n\t_ *jlexer.Lexer\n\t_ *jwriter.Writer\n\t_ easyjson.Marshaler\n)\n\nfunc easyjson1ed00e60DecodeGithubComOlivereElasticV7(in *jlexer.Lexer, out *bulkUpdateRequestCommandOp) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tif isTopLevel {\n\t\t\tin.Consumed()\n\t\t}\n\t\tin.Skip()\n\t\treturn\n\t}\n\tin.Delim('{')\n\tfor !in.IsDelim('}') {\n\t\tkey := in.UnsafeFieldName(false)\n\t\tin.WantColon()\n\t\tif in.IsNull() {\n\t\t\tin.Skip()\n\t\t\tin.WantComma()\n\t\t\tcontinue\n\t\t}\n\t\tswitch key {\n\t\tcase \"_index\":\n\t\t\tout.Index = string(in.String())\n\t\tcase \"_type\":\n\t\t\tout.Type = string(in.String())\n\t\tcase \"_id\":\n\t\t\tout.Id = string(in.String())\n\t\tcase \"parent\":\n\t\t\tout.Parent = string(in.String())\n\t\tcase \"retry_on_conflict\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.RetryOnConflict = nil\n\t\t\t} else {\n\t\t\t\tif out.RetryOnConflict == nil {\n\t\t\t\t\tout.RetryOnConflict = new(int)\n\t\t\t\t}\n\t\t\t\t*out.RetryOnConflict = int(in.Int())\n\t\t\t}\n\t\tcase \"routing\":\n\t\t\tout.Routing = string(in.String())\n\t\tcase \"version\":\n\t\t\tout.Version = int64(in.Int64())\n\t\tcase \"version_type\":\n\t\t\tout.VersionType = string(in.String())\n\t\tcase \"if_seq_no\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.IfSeqNo = nil\n\t\t\t} else {\n\t\t\t\tif out.IfSeqNo == nil {\n\t\t\t\t\tout.IfSeqNo = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.IfSeqNo = int64(in.Int64())\n\t\t\t}\n\t\tcase \"if_primary_term\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.IfPrimaryTerm = nil\n\t\t\t} else {\n\t\t\t\tif out.IfPrimaryTerm == nil {\n\t\t\t\t\tout.IfPrimaryTerm = new(int64)\n\t\t\t\t}\n\t\t\t\t*out.IfPrimaryTerm = int64(in.Int64())\n\t\t\t}\n\t\tdefault:\n\t\t\tin.SkipRecursive()\n\t\t}\n\t\tin.WantComma()\n\t}\n\tin.Delim('}')\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson1ed00e60EncodeGithubComOlivereElasticV7(out *jwriter.Writer, in bulkUpdateRequestCommandOp) {\n\tout.RawByte('{')\n\tfirst := true\n\t_ = first\n\tif in.Index != \"\" {\n\t\tconst prefix string = \",\\\"_index\\\":\"\n\t\tfirst = false\n\t\tout.RawString(prefix[1:])\n\t\tout.String(string(in.Index))\n\t}\n\tif in.Type != \"\" {\n\t\tconst prefix string = \",\\\"_type\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Type))\n\t}\n\tif in.Id != \"\" {\n\t\tconst prefix string = \",\\\"_id\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Id))\n\t}\n\tif in.Parent != \"\" {\n\t\tconst prefix string = \",\\\"parent\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Parent))\n\t}\n\tif in.RetryOnConflict != nil {\n\t\tconst prefix string = \",\\\"retry_on_conflict\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int(int(*in.RetryOnConflict))\n\t}\n\tif in.Routing != \"\" {\n\t\tconst prefix string = \",\\\"routing\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.Routing))\n\t}\n\tif in.Version != 0 {\n\t\tconst prefix string = \",\\\"version\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(in.Version))\n\t}\n\tif in.VersionType != \"\" {\n\t\tconst prefix string = \",\\\"version_type\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.String(string(in.VersionType))\n\t}\n\tif in.IfSeqNo != nil {\n\t\tconst prefix string = \",\\\"if_seq_no\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.IfSeqNo))\n\t}\n\tif in.IfPrimaryTerm != nil {\n\t\tconst prefix string = \",\\\"if_primary_term\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Int64(int64(*in.IfPrimaryTerm))\n\t}\n\tout.RawByte('}')\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v bulkUpdateRequestCommandOp) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson1ed00e60EncodeGithubComOlivereElasticV7(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v bulkUpdateRequestCommandOp) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson1ed00e60EncodeGithubComOlivereElasticV7(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *bulkUpdateRequestCommandOp) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson1ed00e60DecodeGithubComOlivereElasticV7(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *bulkUpdateRequestCommandOp) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson1ed00e60DecodeGithubComOlivereElasticV7(l, v)\n}\nfunc easyjson1ed00e60DecodeGithubComOlivereElasticV71(in *jlexer.Lexer, out *bulkUpdateRequestCommandData) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tif isTopLevel {\n\t\t\tin.Consumed()\n\t\t}\n\t\tin.Skip()\n\t\treturn\n\t}\n\tin.Delim('{')\n\tfor !in.IsDelim('}') {\n\t\tkey := in.UnsafeFieldName(false)\n\t\tin.WantColon()\n\t\tif in.IsNull() {\n\t\t\tin.Skip()\n\t\t\tin.WantComma()\n\t\t\tcontinue\n\t\t}\n\t\tswitch key {\n\t\tcase \"detect_noop\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.DetectNoop = nil\n\t\t\t} else {\n\t\t\t\tif out.DetectNoop == nil {\n\t\t\t\t\tout.DetectNoop = new(bool)\n\t\t\t\t}\n\t\t\t\t*out.DetectNoop = bool(in.Bool())\n\t\t\t}\n\t\tcase \"doc\":\n\t\t\tif m, ok := out.Doc.(easyjson.Unmarshaler); ok {\n\t\t\t\tm.UnmarshalEasyJSON(in)\n\t\t\t} else if m, ok := out.Doc.(json.Unmarshaler); ok {\n\t\t\t\t_ = m.UnmarshalJSON(in.Raw())\n\t\t\t} else {\n\t\t\t\tout.Doc = in.Interface()\n\t\t\t}\n\t\tcase \"doc_as_upsert\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.DocAsUpsert = nil\n\t\t\t} else {\n\t\t\t\tif out.DocAsUpsert == nil {\n\t\t\t\t\tout.DocAsUpsert = new(bool)\n\t\t\t\t}\n\t\t\t\t*out.DocAsUpsert = bool(in.Bool())\n\t\t\t}\n\t\tcase \"script\":\n\t\t\tif m, ok := out.Script.(easyjson.Unmarshaler); ok {\n\t\t\t\tm.UnmarshalEasyJSON(in)\n\t\t\t} else if m, ok := out.Script.(json.Unmarshaler); ok {\n\t\t\t\t_ = m.UnmarshalJSON(in.Raw())\n\t\t\t} else {\n\t\t\t\tout.Script = in.Interface()\n\t\t\t}\n\t\tcase \"scripted_upsert\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.ScriptedUpsert = nil\n\t\t\t} else {\n\t\t\t\tif out.ScriptedUpsert == nil {\n\t\t\t\t\tout.ScriptedUpsert = new(bool)\n\t\t\t\t}\n\t\t\t\t*out.ScriptedUpsert = bool(in.Bool())\n\t\t\t}\n\t\tcase \"upsert\":\n\t\t\tif m, ok := out.Upsert.(easyjson.Unmarshaler); ok {\n\t\t\t\tm.UnmarshalEasyJSON(in)\n\t\t\t} else if m, ok := out.Upsert.(json.Unmarshaler); ok {\n\t\t\t\t_ = m.UnmarshalJSON(in.Raw())\n\t\t\t} else {\n\t\t\t\tout.Upsert = in.Interface()\n\t\t\t}\n\t\tcase \"_source\":\n\t\t\tif in.IsNull() {\n\t\t\t\tin.Skip()\n\t\t\t\tout.Source = nil\n\t\t\t} else {\n\t\t\t\tif out.Source == nil {\n\t\t\t\t\tout.Source = new(bool)\n\t\t\t\t}\n\t\t\t\t*out.Source = bool(in.Bool())\n\t\t\t}\n\t\tdefault:\n\t\t\tin.SkipRecursive()\n\t\t}\n\t\tin.WantComma()\n\t}\n\tin.Delim('}')\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson1ed00e60EncodeGithubComOlivereElasticV71(out *jwriter.Writer, in bulkUpdateRequestCommandData) {\n\tout.RawByte('{')\n\tfirst := true\n\t_ = first\n\tif in.DetectNoop != nil {\n\t\tconst prefix string = \",\\\"detect_noop\\\":\"\n\t\tfirst = false\n\t\tout.RawString(prefix[1:])\n\t\tout.Bool(bool(*in.DetectNoop))\n\t}\n\tif in.Doc != nil {\n\t\tconst prefix string = \",\\\"doc\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tif m, ok := in.Doc.(easyjson.Marshaler); ok {\n\t\t\tm.MarshalEasyJSON(out)\n\t\t} else if m, ok := in.Doc.(json.Marshaler); ok {\n\t\t\tout.Raw(m.MarshalJSON())\n\t\t} else {\n\t\t\tout.Raw(json.Marshal(in.Doc))\n\t\t}\n\t}\n\tif in.DocAsUpsert != nil {\n\t\tconst prefix string = \",\\\"doc_as_upsert\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Bool(bool(*in.DocAsUpsert))\n\t}\n\tif in.Script != nil {\n\t\tconst prefix string = \",\\\"script\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tif m, ok := in.Script.(easyjson.Marshaler); ok {\n\t\t\tm.MarshalEasyJSON(out)\n\t\t} else if m, ok := in.Script.(json.Marshaler); ok {\n\t\t\tout.Raw(m.MarshalJSON())\n\t\t} else {\n\t\t\tout.Raw(json.Marshal(in.Script))\n\t\t}\n\t}\n\tif in.ScriptedUpsert != nil {\n\t\tconst prefix string = \",\\\"scripted_upsert\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Bool(bool(*in.ScriptedUpsert))\n\t}\n\tif in.Upsert != nil {\n\t\tconst prefix string = \",\\\"upsert\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tif m, ok := in.Upsert.(easyjson.Marshaler); ok {\n\t\t\tm.MarshalEasyJSON(out)\n\t\t} else if m, ok := in.Upsert.(json.Marshaler); ok {\n\t\t\tout.Raw(m.MarshalJSON())\n\t\t} else {\n\t\t\tout.Raw(json.Marshal(in.Upsert))\n\t\t}\n\t}\n\tif in.Source != nil {\n\t\tconst prefix string = \",\\\"_source\\\":\"\n\t\tif first {\n\t\t\tfirst = false\n\t\t\tout.RawString(prefix[1:])\n\t\t} else {\n\t\t\tout.RawString(prefix)\n\t\t}\n\t\tout.Bool(bool(*in.Source))\n\t}\n\tout.RawByte('}')\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v bulkUpdateRequestCommandData) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson1ed00e60EncodeGithubComOlivereElasticV71(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v bulkUpdateRequestCommandData) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson1ed00e60EncodeGithubComOlivereElasticV71(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *bulkUpdateRequestCommandData) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson1ed00e60DecodeGithubComOlivereElasticV71(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *bulkUpdateRequestCommandData) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson1ed00e60DecodeGithubComOlivereElasticV71(l, v)\n}\nfunc easyjson1ed00e60DecodeGithubComOlivereElasticV72(in *jlexer.Lexer, out *bulkUpdateRequestCommand) {\n\tisTopLevel := in.IsStart()\n\tif in.IsNull() {\n\t\tin.Skip()\n\t} else {\n\t\tin.Delim('{')\n\t\t*out = make(bulkUpdateRequestCommand)\n\t\tfor !in.IsDelim('}') {\n\t\t\tkey := string(in.String())\n\t\t\tin.WantColon()\n\t\t\tvar v1 bulkUpdateRequestCommandOp\n\t\t\t(v1).UnmarshalEasyJSON(in)\n\t\t\t(*out)[key] = v1\n\t\t\tin.WantComma()\n\t\t}\n\t\tin.Delim('}')\n\t}\n\tif isTopLevel {\n\t\tin.Consumed()\n\t}\n}\nfunc easyjson1ed00e60EncodeGithubComOlivereElasticV72(out *jwriter.Writer, in bulkUpdateRequestCommand) {\n\tif in == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {\n\t\tout.RawString(`null`)\n\t} else {\n\t\tout.RawByte('{')\n\t\tv2First := true\n\t\tfor v2Name, v2Value := range in {\n\t\t\tif v2First {\n\t\t\t\tv2First = false\n\t\t\t} else {\n\t\t\t\tout.RawByte(',')\n\t\t\t}\n\t\t\tout.String(string(v2Name))\n\t\t\tout.RawByte(':')\n\t\t\t(v2Value).MarshalEasyJSON(out)\n\t\t}\n\t\tout.RawByte('}')\n\t}\n}\n\n// MarshalJSON supports json.Marshaler interface\nfunc (v bulkUpdateRequestCommand) MarshalJSON() ([]byte, error) {\n\tw := jwriter.Writer{}\n\teasyjson1ed00e60EncodeGithubComOlivereElasticV72(&w, v)\n\treturn w.Buffer.BuildBytes(), w.Error\n}\n\n// MarshalEasyJSON supports easyjson.Marshaler interface\nfunc (v bulkUpdateRequestCommand) MarshalEasyJSON(w *jwriter.Writer) {\n\teasyjson1ed00e60EncodeGithubComOlivereElasticV72(w, v)\n}\n\n// UnmarshalJSON supports json.Unmarshaler interface\nfunc (v *bulkUpdateRequestCommand) UnmarshalJSON(data []byte) error {\n\tr := jlexer.Lexer{Data: data}\n\teasyjson1ed00e60DecodeGithubComOlivereElasticV72(&r, v)\n\treturn r.Error()\n}\n\n// UnmarshalEasyJSON supports easyjson.Unmarshaler interface\nfunc (v *bulkUpdateRequestCommand) UnmarshalEasyJSON(l *jlexer.Lexer) {\n\teasyjson1ed00e60DecodeGithubComOlivereElasticV72(l, v)\n}\n"
  },
  {
    "path": "bulk_update_request_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestBulkUpdateRequestSerialization(t *testing.T) {\n\trawJson := json.RawMessage(`{\"counter\":42}`)\n\trawString := `{\"counter\":42}`\n\ttests := []struct {\n\t\tRequest  BulkableRequest\n\t\tExpected []string\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"1\").Doc(struct {\n\t\t\t\tCounter int64 `json:\"counter\"`\n\t\t\t}{\n\t\t\t\tCounter: 42,\n\t\t\t}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"1\"}}`,\n\t\t\t\t`{\"doc\":{\"counter\":42}}`,\n\t\t\t},\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"1\").\n\t\t\t\tRouting(\"123\").\n\t\t\t\tRetryOnConflict(3).\n\t\t\t\tDocAsUpsert(true).\n\t\t\t\tDoc(struct {\n\t\t\t\t\tCounter int64 `json:\"counter\"`\n\t\t\t\t}{\n\t\t\t\t\tCounter: 42,\n\t\t\t\t}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"1\",\"retry_on_conflict\":3,\"routing\":\"123\"}}`,\n\t\t\t\t`{\"doc\":{\"counter\":42},\"doc_as_upsert\":true}`,\n\t\t\t},\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"1\").\n\t\t\t\tRetryOnConflict(3).\n\t\t\t\tScript(NewScript(`ctx._source.retweets += param1`).Lang(\"javascript\").Param(\"param1\", 42)).\n\t\t\t\tUpsert(struct {\n\t\t\t\t\tCounter int64 `json:\"counter\"`\n\t\t\t\t}{\n\t\t\t\t\tCounter: 42,\n\t\t\t\t}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"1\",\"retry_on_conflict\":3}}`,\n\t\t\t\t`{\"script\":{\"lang\":\"javascript\",\"params\":{\"param1\":42},\"source\":\"ctx._source.retweets += param1\"},\"upsert\":{\"counter\":42}}`,\n\t\t\t},\n\t\t},\n\t\t// #3\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"1\").DetectNoop(true).Doc(struct {\n\t\t\t\tCounter int64 `json:\"counter\"`\n\t\t\t}{\n\t\t\t\tCounter: 42,\n\t\t\t}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"1\"}}`,\n\t\t\t\t`{\"detect_noop\":true,\"doc\":{\"counter\":42}}`,\n\t\t\t},\n\t\t},\n\t\t// #4\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"1\").\n\t\t\t\tRetryOnConflict(3).\n\t\t\t\tScriptedUpsert(true).\n\t\t\t\tScript(NewScript(`ctx._source.retweets += param1`).Lang(\"javascript\").Param(\"param1\", 42)).\n\t\t\t\tUpsert(struct {\n\t\t\t\t\tCounter int64 `json:\"counter\"`\n\t\t\t\t}{\n\t\t\t\t\tCounter: 42,\n\t\t\t\t}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"1\",\"retry_on_conflict\":3}}`,\n\t\t\t\t`{\"script\":{\"lang\":\"javascript\",\"params\":{\"param1\":42},\"source\":\"ctx._source.retweets += param1\"},\"scripted_upsert\":true,\"upsert\":{\"counter\":42}}`,\n\t\t\t},\n\t\t},\n\t\t// #5\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"4\").ReturnSource(true).Doc(struct {\n\t\t\t\tCounter int64 `json:\"counter\"`\n\t\t\t}{\n\t\t\t\tCounter: 42,\n\t\t\t}),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"4\"}}`,\n\t\t\t\t`{\"doc\":{\"counter\":42},\"_source\":true}`,\n\t\t\t},\n\t\t},\n\t\t// #6\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"4\").\n\t\t\t\tReturnSource(true).\n\t\t\t\tDoc(`{\"counter\":42}`),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"4\"}}`,\n\t\t\t\t`{\"doc\":{\"counter\":42},\"_source\":true}`,\n\t\t\t},\n\t\t},\n\t\t// #7\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"4\").\n\t\t\t\tReturnSource(true).\n\t\t\t\tDoc(json.RawMessage(`{\"counter\":42}`)),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"4\"}}`,\n\t\t\t\t`{\"doc\":{\"counter\":42},\"_source\":true}`,\n\t\t\t},\n\t\t},\n\t\t// #8\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"4\").\n\t\t\t\tReturnSource(true).\n\t\t\t\tDoc(&rawJson),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"4\"}}`,\n\t\t\t\t`{\"doc\":{\"counter\":42},\"_source\":true}`,\n\t\t\t},\n\t\t},\n\t\t// #9\n\t\t{\n\t\t\tRequest: NewBulkUpdateRequest().Index(\"index1\").Id(\"4\").\n\t\t\t\tReturnSource(true).\n\t\t\t\tDoc(&rawString),\n\t\t\tExpected: []string{\n\t\t\t\t`{\"update\":{\"_index\":\"index1\",\"_id\":\"4\"}}`,\n\t\t\t\t`{\"doc\":{\"counter\":42},\"_source\":true}`,\n\t\t\t},\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tlines, err := test.Request.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: expected no error, got: %v\", i, err)\n\t\t}\n\t\tif lines == nil {\n\t\t\tt.Fatalf(\"#%d: expected lines, got nil\", i)\n\t\t}\n\t\tif len(lines) != len(test.Expected) {\n\t\t\tt.Fatalf(\"#%d: expected %d lines, got %d\", i, len(test.Expected), len(lines))\n\t\t}\n\t\tfor j, line := range lines {\n\t\t\tif line != test.Expected[j] {\n\t\t\t\tt.Errorf(\"#%d: expected line #%d to be\\n%s\\nbut got:\\n%s\", i, j, test.Expected[j], line)\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar bulkUpdateRequestSerializationResult string\n\nfunc BenchmarkBulkUpdateRequestSerialization(b *testing.B) {\n\tb.Run(\"stdlib\", func(b *testing.B) {\n\t\tr := NewBulkUpdateRequest().Index(\"index1\").Id(\"1\").Doc(struct {\n\t\t\tCounter int64 `json:\"counter\"`\n\t\t}{\n\t\t\tCounter: 42,\n\t\t})\n\t\tbenchmarkBulkUpdateRequestSerialization(b, r.UseEasyJSON(false))\n\t})\n\tb.Run(\"easyjson\", func(b *testing.B) {\n\t\tr := NewBulkUpdateRequest().Index(\"index1\").Id(\"1\").Doc(struct {\n\t\t\tCounter int64 `json:\"counter\"`\n\t\t}{\n\t\t\tCounter: 42,\n\t\t}).UseEasyJSON(false)\n\t\tbenchmarkBulkUpdateRequestSerialization(b, r.UseEasyJSON(true))\n\t})\n}\n\nfunc benchmarkBulkUpdateRequestSerialization(b *testing.B, r *BulkUpdateRequest) {\n\tvar s string\n\tfor n := 0; n < b.N; n++ {\n\t\ts = r.String()\n\t\tr.source = nil // Don't let caching spoil the benchmark\n\t}\n\tbulkUpdateRequestSerializationResult = s // ensure the compiler doesn't optimize\n\tb.ReportAllocs()\n}\n"
  },
  {
    "path": "canonicalize.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"net/url\"\n\t\"strings\"\n)\n\n// canonicalize takes a list of URLs and returns its canonicalized form, i.e.\n// remove anything but scheme, userinfo, host, path, and port.\n// It also removes all trailing slashes. Invalid URLs or URLs that do not\n// use protocol http or https are skipped.\n//\n// Example:\n// http://127.0.0.1:9200/?query=1 -> http://127.0.0.1:9200\n// http://127.0.0.1:9200/db1/ -> http://127.0.0.1:9200/db1\n// http://127.0.0.1:9200/db1/// -> http://127.0.0.1:9200/db1\nfunc canonicalize(rawurls ...string) []string {\n\tvar canonicalized []string\n\tfor _, rawurl := range rawurls {\n\t\tu, err := url.Parse(rawurl)\n\t\tif err == nil {\n\t\t\tif u.Scheme == \"http\" || u.Scheme == \"https\" {\n\t\t\t\t// Trim trailing slashes. Notice that strings.TrimSuffix will only remove the last slash,\n\t\t\t\t// not all slashes from the suffix, so we'll loop over the path to remove all slashes.\n\t\t\t\tfor strings.HasSuffix(u.Path, \"/\") {\n\t\t\t\t\tu.Path = u.Path[:len(u.Path)-1]\n\t\t\t\t}\n\t\t\t\tu.Fragment = \"\"\n\t\t\t\tu.RawQuery = \"\"\n\t\t\t\tcanonicalized = append(canonicalized, u.String())\n\t\t\t}\n\t\t}\n\t}\n\treturn canonicalized\n}\n"
  },
  {
    "path": "canonicalize_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestCanonicalize(t *testing.T) {\n\ttests := []struct {\n\t\tInput  []string\n\t\tOutput []string\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tInput:  []string{\"http://127.0.0.1/\"},\n\t\t\tOutput: []string{\"http://127.0.0.1\"},\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tInput:  []string{\"http://127.0.0.1:9200/\", \"gopher://golang.org/\", \"http://127.0.0.1:9201\"},\n\t\t\tOutput: []string{\"http://127.0.0.1:9200\", \"http://127.0.0.1:9201\"},\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tInput:  []string{\"http://user:secret@127.0.0.1/path?query=1#fragment\"},\n\t\t\tOutput: []string{\"http://user:secret@127.0.0.1/path\"},\n\t\t},\n\t\t// #3\n\t\t{\n\t\t\tInput:  []string{\"https://somewhere.on.mars:9999/path?query=1#fragment\"},\n\t\t\tOutput: []string{\"https://somewhere.on.mars:9999/path\"},\n\t\t},\n\t\t// #4\n\t\t{\n\t\t\tInput:  []string{\"https://prod1:9999/one?query=1#fragment\", \"https://prod2:9998/two?query=1#fragment\"},\n\t\t\tOutput: []string{\"https://prod1:9999/one\", \"https://prod2:9998/two\"},\n\t\t},\n\t\t// #5\n\t\t{\n\t\t\tInput:  []string{\"http://127.0.0.1/one/\"},\n\t\t\tOutput: []string{\"http://127.0.0.1/one\"},\n\t\t},\n\t\t// #6\n\t\t{\n\t\t\tInput:  []string{\"http://127.0.0.1/one///\"},\n\t\t\tOutput: []string{\"http://127.0.0.1/one\"},\n\t\t},\n\t\t// #7: Invalid URL\n\t\t{\n\t\t\tInput:  []string{\"127.0.0.1/\"},\n\t\t\tOutput: []string{},\n\t\t},\n\t\t// #8: Invalid URL\n\t\t{\n\t\t\tInput:  []string{\"127.0.0.1:9200\"},\n\t\t\tOutput: []string{},\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tgot := canonicalize(test.Input...)\n\t\tif want, have := len(test.Output), len(got); want != have {\n\t\t\tt.Fatalf(\"#%d: expected %d elements; got: %d\", i, want, have)\n\t\t}\n\t\tfor i := 0; i < len(got); i++ {\n\t\t\tif want, have := test.Output[i], got[i]; want != have {\n\t\t\t\tt.Errorf(\"#%d: expected %q; got: %q\", i, want, have)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cat_aliases.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// CatAliasesService shows information about currently configured aliases\n// to indices including filter and routing infos.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cat-aliases.html\n// for details.\ntype CatAliasesService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tlocal         *bool\n\tmasterTimeout string\n\taliases       []string\n\tcolumns       []string\n\tsort          []string // list of columns for sort order\n}\n\n// NewCatAliasesService creates a new CatAliasesService.\nfunc NewCatAliasesService(client *Client) *CatAliasesService {\n\treturn &CatAliasesService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CatAliasesService) Pretty(pretty bool) *CatAliasesService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CatAliasesService) Human(human bool) *CatAliasesService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CatAliasesService) ErrorTrace(errorTrace bool) *CatAliasesService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CatAliasesService) FilterPath(filterPath ...string) *CatAliasesService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CatAliasesService) Header(name string, value string) *CatAliasesService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CatAliasesService) Headers(headers http.Header) *CatAliasesService {\n\ts.headers = headers\n\treturn s\n}\n\n// Alias specifies one or more aliases to which information should be returned.\nfunc (s *CatAliasesService) Alias(alias ...string) *CatAliasesService {\n\ts.aliases = alias\n\treturn s\n}\n\n// Local indicates to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *CatAliasesService) Local(local bool) *CatAliasesService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout is the explicit operation timeout for connection to master node.\nfunc (s *CatAliasesService) MasterTimeout(masterTimeout string) *CatAliasesService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Columns to return in the response.\n// To get a list of all possible columns to return, run the following command\n// in your terminal:\n//\n// Example:\n//   curl 'http://localhost:9200/_cat/aliases?help'\n//\n// You can use Columns(\"*\") to return all possible columns. That might take\n// a little longer than the default set of columns.\nfunc (s *CatAliasesService) Columns(columns ...string) *CatAliasesService {\n\ts.columns = columns\n\treturn s\n}\n\n// Sort is a list of fields to sort by.\nfunc (s *CatAliasesService) Sort(fields ...string) *CatAliasesService {\n\ts.sort = fields\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *CatAliasesService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\n\tif len(s.aliases) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_cat/aliases/{name}\", map[string]string{\n\t\t\t\"name\": strings.Join(s.aliases, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_cat/aliases\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{\n\t\t\"format\": []string{\"json\"}, // always returns as JSON\n\t}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"s\", strings.Join(s.sort, \",\"))\n\t}\n\tif len(s.columns) > 0 {\n\t\tparams.Set(\"h\", strings.Join(s.columns, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *CatAliasesService) Do(ctx context.Context) (CatAliasesResponse, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret CatAliasesResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// CatAliasesResponse is the outcome of CatAliasesService.Do.\ntype CatAliasesResponse []CatAliasesResponseRow\n\n// CatAliasesResponseRow is a single row in a CatAliasesResponse.\n// Notice that not all of these fields might be filled; that depends\n// on the number of columns chose in the request (see CatAliasesService.Columns).\ntype CatAliasesResponseRow struct {\n\t// Alias name.\n\tAlias string `json:\"alias\"`\n\t// Index the alias points to.\n\tIndex string `json:\"index\"`\n\t// Filter, e.g. \"*\" or \"-\".\n\tFilter string `json:\"filter\"`\n\t// RoutingIndex specifies the index routing (or \"-\").\n\tRoutingIndex string `json:\"routing.index\"`\n\t// RoutingSearch specifies the search routing (or \"-\").\n\tRoutingSearch string `json:\"routing.search\"`\n\t// IsWriteIndex indicates whether the index can be written to (or \"-\").\n\tIsWriteIndex string `json:\"is_write_index\"`\n}\n"
  },
  {
    "path": "cat_aliases_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCatAliases(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\n\t// Add two aliases\n\t_, err := client.Alias().\n\t\tAdd(testIndexName, testAliasName).\n\t\tAction(NewAliasAddAction(testAliasName2).Index(testIndexName2)).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\t// Remove aliases\n\t\tclient.Alias().\n\t\t\tRemove(testIndexName, testAliasName).\n\t\t\tRemove(testIndexName2, testAliasName2).\n\t\t\tDo(context.TODO())\n\t}()\n\n\t// Check all aliases\n\tres, err := client.CatAliases().Pretty(true).Columns(\"*\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif want, have := 2, len(res); want != have {\n\t\tt.Fatalf(\"want len=%d, have %d\", want, have)\n\t}\n\n\t// Check a named alias\n\tres, err = client.CatAliases().Alias(testAliasName).Pretty(true).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif want, have := 1, len(res); want != have {\n\t\tt.Fatalf(\"want len=%d, have %d\", want, have)\n\t}\n}\n"
  },
  {
    "path": "cat_allocation.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// CatAllocationService provides a snapshot of how many shards are allocated\n// to each data node and how much disk space they are using.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cat-allocation.html\n// for details.\ntype CatAllocationService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tbytes         string // b, k, m, or g\n\tlocal         *bool\n\tmasterTimeout string\n\tnodes         []string\n\tcolumns       []string\n\tsort          []string // list of columns for sort order\n}\n\n// NewCatAllocationService creates a new CatAllocationService.\nfunc NewCatAllocationService(client *Client) *CatAllocationService {\n\treturn &CatAllocationService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CatAllocationService) Pretty(pretty bool) *CatAllocationService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CatAllocationService) Human(human bool) *CatAllocationService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CatAllocationService) ErrorTrace(errorTrace bool) *CatAllocationService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CatAllocationService) FilterPath(filterPath ...string) *CatAllocationService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CatAllocationService) Header(name string, value string) *CatAllocationService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CatAllocationService) Headers(headers http.Header) *CatAllocationService {\n\ts.headers = headers\n\treturn s\n}\n\n// NodeID specifies one or more node IDs to for information should be returned.\nfunc (s *CatAllocationService) NodeID(nodes ...string) *CatAllocationService {\n\ts.nodes = nodes\n\treturn s\n}\n\n// Bytes represents the unit in which to display byte values.\n// Valid values are: \"b\", \"k\", \"m\", or \"g\".\nfunc (s *CatAllocationService) Bytes(bytes string) *CatAllocationService {\n\ts.bytes = bytes\n\treturn s\n}\n\n// Local indicates to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *CatAllocationService) Local(local bool) *CatAllocationService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout is the explicit operation timeout for connection to master node.\nfunc (s *CatAllocationService) MasterTimeout(masterTimeout string) *CatAllocationService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Columns to return in the response.\n// To get a list of all possible columns to return, run the following command\n// in your terminal:\n//\n// Example:\n//   curl 'http://localhost:9200/_cat/aliases?help'\n//\n// You can use Columns(\"*\") to return all possible columns. That might take\n// a little longer than the default set of columns.\nfunc (s *CatAllocationService) Columns(columns ...string) *CatAllocationService {\n\ts.columns = columns\n\treturn s\n}\n\n// Sort is a list of fields to sort by.\nfunc (s *CatAllocationService) Sort(fields ...string) *CatAllocationService {\n\ts.sort = fields\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *CatAllocationService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\n\tif len(s.nodes) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_cat/allocation/{node_id}\", map[string]string{\n\t\t\t\"node_id\": strings.Join(s.nodes, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_cat/allocation\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{\n\t\t\"format\": []string{\"json\"}, // always returns as JSON\n\t}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.bytes != \"\" {\n\t\tparams.Set(\"bytes\", s.bytes)\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"s\", strings.Join(s.sort, \",\"))\n\t}\n\tif len(s.columns) > 0 {\n\t\tparams.Set(\"h\", strings.Join(s.columns, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *CatAllocationService) Do(ctx context.Context) (CatAllocationResponse, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret CatAllocationResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// CatAllocationResponse is the outcome of CatAllocationService.Do.\ntype CatAllocationResponse []CatAllocationResponseRow\n\n// CatAllocationResponseRow is a single row in a CatAllocationResponse.\n// Notice that not all of these fields might be filled; that depends\n// on the number of columns chose in the request (see CatAllocationService.Columns).\ntype CatAllocationResponseRow struct {\n\t// Shards represents the number of shards on a node.\n\tShards int `json:\"shards,string\"`\n\t// DiskIndices represents the disk used by ES indices, e.g. \"46.1kb\".\n\tDiskIndices string `json:\"disk.indices\"`\n\t// DiskUsed represents the disk used (total, not just ES), e.g. \"34.5gb\"\n\tDiskUsed string `json:\"disk.used\"`\n\t// DiskAvail represents the disk available, e.g. \"53.2gb\".\n\tDiskAvail string `json:\"disk.avail\"`\n\t// DiskTotal represents the total capacity of all volumes, e.g. \"87.7gb\".\n\tDiskTotal string `json:\"disk.total\"`\n\t// DiskPercent represents the percent of disk used, e.g. 39.\n\tDiskPercent int `json:\"disk.percent,string\"`\n\t// Host represents the hostname of the node.\n\tHost string `json:\"host\"`\n\t// IP represents the IP address of the node.\n\tIP string `json:\"ip\"`\n\t// Node represents the node ID.\n\tNode string `json:\"node\"`\n}\n"
  },
  {
    "path": "cat_allocation_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCatAllocation(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\tres, err := client.CatAllocation().Columns(\"*\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\tif have := res[0].IP; have == \"\" {\n\t\tt.Fatalf(\"IP[0]: want != %q, have %q\", \"\", have)\n\t}\n}\n"
  },
  {
    "path": "cat_count.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// CatCountService provides quick access to the document count of the entire cluster,\n// or individual indices.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cat-count.html\n// for details.\ntype CatCountService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex         []string\n\tlocal         *bool\n\tmasterTimeout string\n\tcolumns       []string\n\tsort          []string // list of columns for sort order\n}\n\n// NewCatCountService creates a new CatCountService.\nfunc NewCatCountService(client *Client) *CatCountService {\n\treturn &CatCountService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CatCountService) Pretty(pretty bool) *CatCountService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CatCountService) Human(human bool) *CatCountService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CatCountService) ErrorTrace(errorTrace bool) *CatCountService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CatCountService) FilterPath(filterPath ...string) *CatCountService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CatCountService) Header(name string, value string) *CatCountService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CatCountService) Headers(headers http.Header) *CatCountService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index specifies zero or more indices for which to return counts\n// (by default counts for all indices are returned).\nfunc (s *CatCountService) Index(index ...string) *CatCountService {\n\ts.index = index\n\treturn s\n}\n\n// Local indicates to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *CatCountService) Local(local bool) *CatCountService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout is the explicit operation timeout for connection to master node.\nfunc (s *CatCountService) MasterTimeout(masterTimeout string) *CatCountService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Columns to return in the response.\n// To get a list of all possible columns to return, run the following command\n// in your terminal:\n//\n// Example:\n//   curl 'http://localhost:9200/_cat/count?help'\n//\n// You can use Columns(\"*\") to return all possible columns. That might take\n// a little longer than the default set of columns.\nfunc (s *CatCountService) Columns(columns ...string) *CatCountService {\n\ts.columns = columns\n\treturn s\n}\n\n// Sort is a list of fields to sort by.\nfunc (s *CatCountService) Sort(fields ...string) *CatCountService {\n\ts.sort = fields\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *CatCountService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_cat/count/{index}\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_cat/count\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{\n\t\t\"format\": []string{\"json\"}, // always returns as JSON\n\t}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"s\", strings.Join(s.sort, \",\"))\n\t}\n\tif len(s.columns) > 0 {\n\t\tparams.Set(\"h\", strings.Join(s.columns, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *CatCountService) Do(ctx context.Context) (CatCountResponse, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret CatCountResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// CatCountResponse is the outcome of CatCountService.Do.\ntype CatCountResponse []CatCountResponseRow\n\n// CatCountResponseRow specifies the data returned for one index\n// of a CatCountResponse. Notice that not all of these fields might\n// be filled; that depends on the number of columns chose in the\n// request (see CatCountService.Columns).\ntype CatCountResponseRow struct {\n\tEpoch     int64  `json:\"epoch,string\"` // e.g. 1527077996\n\tTimestamp string `json:\"timestamp\"`    // e.g. \"12:19:56\"\n\tCount     int    `json:\"count,string\"` // number of documents\n}\n"
  },
  {
    "path": "cat_count_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCatCountIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tvar (\n\t\ttotal   int64\n\t\tindices = []string{testIndexName, testIndexName2, testOrderIndex}\n\t)\n\n\tfor _, index := range indices {\n\t\tcount, err := client.Count(index).Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\ttotal += count\n\t}\n\n\tresp, err := client.CatCount().\n\t\tIndex(indices...).\n\t\tColumns(\"*\").\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif want, have := 1, len(resp); want != have {\n\t\tt.Fatalf(\"expected %d response item, got %d\", want, have)\n\t}\n\n\tif want, have := total, int64(resp[0].Count); want != have {\n\t\tt.Fatalf(\"expected %d documents, got %d\", want, have)\n\t}\n}\n"
  },
  {
    "path": "cat_count_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCatCount(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\tres, err := client.CatCount().Pretty(true).Columns(\"*\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\tif have := res[0].Count; have <= 0 {\n\t\tt.Fatalf(\"Count[0]: want > %d, have %d\", 0, have)\n\t}\n}\n"
  },
  {
    "path": "cat_fielddata.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// CatFielddataService Returns the amount of heap memory currently used by\n// the field data cache on every data node in the cluster.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.12/cat-fielddata.html\n// for details.\ntype CatFielddataService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tfields  []string // list of fields used to limit returned information\n\tbytes   string   // b, k, m, or g\n\tcolumns []string\n\tsort    []string // list of columns for sort order\n}\n\n// NewCatFielddataService creates a new NewCatFielddataService.\nfunc NewCatFielddataService(client *Client) *CatFielddataService {\n\treturn &CatFielddataService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CatFielddataService) Pretty(pretty bool) *CatFielddataService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CatFielddataService) Human(human bool) *CatFielddataService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CatFielddataService) ErrorTrace(errorTrace bool) *CatFielddataService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CatFielddataService) FilterPath(filterPath ...string) *CatFielddataService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CatFielddataService) Header(name string, value string) *CatFielddataService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CatFielddataService) Headers(headers http.Header) *CatFielddataService {\n\ts.headers = headers\n\treturn s\n}\n\n// Fielddata specifies one or more node IDs to for information should be returned.\nfunc (s *CatFielddataService) Field(fields ...string) *CatFielddataService {\n\ts.fields = fields\n\treturn s\n}\n\n// Bytes represents the unit in which to display byte values.\n// Valid values are: \"b\", \"k\", \"m\", or \"g\".\nfunc (s *CatFielddataService) Bytes(bytes string) *CatFielddataService {\n\ts.bytes = bytes\n\treturn s\n}\n\n// Columns to return in the response.\n// To get a list of all possible columns to return, run the following command\n// in your terminal:\n//\n// Example:\n//   curl 'http://localhost:9200/_cat/fielddata?help'\n//\n// You can use Columns(\"*\") to return all possible columns. That might take\n// a little longer than the default set of columns.\nfunc (s *CatFielddataService) Columns(columns ...string) *CatFielddataService {\n\ts.columns = columns\n\treturn s\n}\n\n// Sort is a list of fields to sort by.\nfunc (s *CatFielddataService) Sort(fields ...string) *CatFielddataService {\n\ts.sort = fields\n\treturn s\n}\n\nfunc (s *CatFielddataService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\n\tif len(s.fields) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_cat/fielddata/{field}\", map[string]string{\n\t\t\t\"field\": strings.Join(s.fields, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_cat/fielddata/\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{\n\t\t\"format\": []string{\"json\"}, // always returns as JSON\n\t}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.bytes != \"\" {\n\t\tparams.Set(\"bytes\", s.bytes)\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"s\", strings.Join(s.sort, \",\"))\n\t}\n\tif len(s.columns) > 0 {\n\t\tparams.Set(\"h\", strings.Join(s.columns, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *CatFielddataService) Do(ctx context.Context) (CatFielddataResponse, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret CatFielddataResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// CatFielddataResponse is the outcome of CatFielddataService.Do.\ntype CatFielddataResponse []CatFielddataResponseRow\n\n// CatFielddataResponseRow is a single row in a CatFielddataResponse.\n// Notice that not all of these fields might be filled; that depends on\n// the number of columns chose in the request (see CatFielddataService.Columns).\ntype CatFielddataResponseRow struct {\n\t// Id represents the id of the fielddata.\n\tId string `json:\"id\"`\n\t// Host represents the hostname of the fielddata.\n\tHost string `json:\"host\"`\n\t// IP represents the IP address of the fielddata.\n\tIP string `json:\"ip\"`\n\t// Node represents the Node name of the fielddata.\n\tNode string `json:\"node\"`\n\t// Field represents the name of the fielddata.\n\tField string `json:\"field\"`\n\t// Size represents the size of the fielddata, e.g. \"53.2gb\".\n\tSize string `json:\"size\"`\n}\n"
  },
  {
    "path": "cat_fielddata_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCatFielddata(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\n\t// generate fielddata by aggregation\n\taggRes, err := client.Search(testIndexName).\n\t\tAggregation(\"gene_message_fielddata\", NewTermsAggregation().Field(\"message\")).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif aggRes == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\n\tres, err := client.CatFielddata().Pretty(true).Columns(\"*\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\n\t// check fielddata \"message\" in response\n\tvar found bool\n\tfor _, fielddata := range res {\n\t\tif fielddata.Field == \"message\" {\n\t\t\tfound = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !found {\n\t\tt.Fatal(\"fielddata message not found\")\n\t}\n\n}\n"
  },
  {
    "path": "cat_health.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// CatHealthService returns a terse representation of the same information\n// as /_cluster/health.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cat-health.html\n// for details.\ntype CatHealthService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tlocal               *bool\n\tmasterTimeout       string\n\tcolumns             []string\n\tsort                []string // list of columns for sort order\n\tdisableTimestamping *bool\n}\n\n// NewCatHealthService creates a new CatHealthService.\nfunc NewCatHealthService(client *Client) *CatHealthService {\n\treturn &CatHealthService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CatHealthService) Pretty(pretty bool) *CatHealthService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CatHealthService) Human(human bool) *CatHealthService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CatHealthService) ErrorTrace(errorTrace bool) *CatHealthService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CatHealthService) FilterPath(filterPath ...string) *CatHealthService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CatHealthService) Header(name string, value string) *CatHealthService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CatHealthService) Headers(headers http.Header) *CatHealthService {\n\ts.headers = headers\n\treturn s\n}\n\n// Local indicates to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *CatHealthService) Local(local bool) *CatHealthService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout is the explicit operation timeout for connection to master node.\nfunc (s *CatHealthService) MasterTimeout(masterTimeout string) *CatHealthService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Columns to return in the response.\n// To get a list of all possible columns to return, run the following command\n// in your terminal:\n//\n// Example:\n//   curl 'http://localhost:9200/_cat/indices?help'\n//\n// You can use Columns(\"*\") to return all possible columns. That might take\n// a little longer than the default set of columns.\nfunc (s *CatHealthService) Columns(columns ...string) *CatHealthService {\n\ts.columns = columns\n\treturn s\n}\n\n// Sort is a list of fields to sort by.\nfunc (s *CatHealthService) Sort(fields ...string) *CatHealthService {\n\ts.sort = fields\n\treturn s\n}\n\n// DisableTimestamping disables timestamping (default: true).\nfunc (s *CatHealthService) DisableTimestamping(disable bool) *CatHealthService {\n\ts.disableTimestamping = &disable\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *CatHealthService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath := \"/_cat/health\"\n\n\t// Add query string parameters\n\tparams := url.Values{\n\t\t\"format\": []string{\"json\"}, // always returns as JSON\n\t}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"s\", strings.Join(s.sort, \",\"))\n\t}\n\tif v := s.disableTimestamping; v != nil {\n\t\tparams.Set(\"ts\", fmt.Sprint(*v))\n\t}\n\tif len(s.columns) > 0 {\n\t\tparams.Set(\"h\", strings.Join(s.columns, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *CatHealthService) Do(ctx context.Context) (CatHealthResponse, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret CatHealthResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// CatHealthResponse is the outcome of CatHealthService.Do.\ntype CatHealthResponse []CatHealthResponseRow\n\n// CatHealthResponseRow is a single row in a CatHealthResponse.\n// Notice that not all of these fields might be filled; that depends\n// on the number of columns chose in the request (see CatHealthService.Columns).\ntype CatHealthResponseRow struct {\n\tEpoch               int64  `json:\"epoch,string\"`          // e.g. 1527077996\n\tTimestamp           string `json:\"timestamp\"`             // e.g. \"12:19:56\"\n\tCluster             string `json:\"cluster\"`               // cluster name, e.g. \"elasticsearch\"\n\tStatus              string `json:\"status\"`                // health status, e.g. \"green\", \"yellow\", or \"red\"\n\tNodeTotal           int    `json:\"node.total,string\"`     // total number of nodes\n\tNodeData            int    `json:\"node.data,string\"`      // number of nodes that can store data\n\tShards              int    `json:\"shards,string\"`         // total number of shards\n\tPri                 int    `json:\"pri,string\"`            // number of primary shards\n\tRelo                int    `json:\"relo,string\"`           // number of relocating nodes\n\tInit                int    `json:\"init,string\"`           // number of initializing nodes\n\tUnassign            int    `json:\"unassign,string\"`       // number of unassigned shards\n\tPendingTasks        int    `json:\"pending_tasks,string\"`  // number of pending tasks\n\tMaxTaskWaitTime     string `json:\"max_task_wait_time\"`    // wait time of longest task pending, e.g. \"-\" or time in millis\n\tActiveShardsPercent string `json:\"active_shards_percent\"` // active number of shards in percent, e.g. \"100%\"\n}\n"
  },
  {
    "path": "cat_health_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCatHealth(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\tres, err := client.CatHealth().Columns(\"*\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\tif have := res[0].Cluster; have == \"\" {\n\t\tt.Fatalf(\"Cluster[0]: want != %q, have %q\", \"\", have)\n\t}\n}\n"
  },
  {
    "path": "cat_indices.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// CatIndicesService returns the list of indices plus some additional\n// information about them.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cat-indices.html\n// for details.\ntype CatIndicesService struct {\n\tclient *Client\n\n\tpretty     *bool    // pretty format the returned JSON response\n\thuman      *bool    // return human readable values for statistics\n\terrorTrace *bool    // include the stack trace of returned errors\n\tfilterPath []string // list of filters used to reduce the response\n\n\tindex         string\n\tbytes         string // b, k, m, or g\n\tlocal         *bool\n\tmasterTimeout string\n\tcolumns       []string\n\thealth        string   // green, yellow, or red\n\tprimaryOnly   *bool    // true for primary shards only\n\tsort          []string // list of columns for sort order\n\theaders       http.Header\n}\n\n// NewCatIndicesService creates a new CatIndicesService.\nfunc NewCatIndicesService(client *Client) *CatIndicesService {\n\treturn &CatIndicesService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CatIndicesService) Pretty(pretty bool) *CatIndicesService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CatIndicesService) Human(human bool) *CatIndicesService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CatIndicesService) ErrorTrace(errorTrace bool) *CatIndicesService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CatIndicesService) FilterPath(filterPath ...string) *CatIndicesService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CatIndicesService) Header(name string, value string) *CatIndicesService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CatIndicesService) Headers(headers http.Header) *CatIndicesService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the index to list (by default all indices are returned).\nfunc (s *CatIndicesService) Index(index string) *CatIndicesService {\n\ts.index = index\n\treturn s\n}\n\n// Bytes represents the unit in which to display byte values.\n// Valid values are: \"b\", \"k\", \"m\", or \"g\".\nfunc (s *CatIndicesService) Bytes(bytes string) *CatIndicesService {\n\ts.bytes = bytes\n\treturn s\n}\n\n// Local indicates to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *CatIndicesService) Local(local bool) *CatIndicesService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout is the explicit operation timeout for connection to master node.\nfunc (s *CatIndicesService) MasterTimeout(masterTimeout string) *CatIndicesService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Columns to return in the response.\n// To get a list of all possible columns to return, run the following command\n// in your terminal:\n//\n// Example:\n//   curl 'http://localhost:9200/_cat/indices?help'\n//\n// You can use Columns(\"*\") to return all possible columns. That might take\n// a little longer than the default set of columns.\nfunc (s *CatIndicesService) Columns(columns ...string) *CatIndicesService {\n\ts.columns = columns\n\treturn s\n}\n\n// Health filters indices by their health status.\n// Valid values are: \"green\", \"yellow\", or \"red\".\nfunc (s *CatIndicesService) Health(healthState string) *CatIndicesService {\n\ts.health = healthState\n\treturn s\n}\n\n// PrimaryOnly when set to true returns stats only for primary shards (default: false).\nfunc (s *CatIndicesService) PrimaryOnly(primaryOnly bool) *CatIndicesService {\n\ts.primaryOnly = &primaryOnly\n\treturn s\n}\n\n// Sort is a list of fields to sort by.\nfunc (s *CatIndicesService) Sort(fields ...string) *CatIndicesService {\n\ts.sort = fields\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *CatIndicesService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\n\tif s.index != \"\" {\n\t\tpath, err = uritemplates.Expand(\"/_cat/indices/{index}\", map[string]string{\n\t\t\t\"index\": s.index,\n\t\t})\n\t} else {\n\t\tpath = \"/_cat/indices\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{\n\t\t\"format\": []string{\"json\"}, // always returns as JSON\n\t}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.bytes != \"\" {\n\t\tparams.Set(\"bytes\", s.bytes)\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif len(s.columns) > 0 {\n\t\t// loop through all columns and apply alias if needed\n\t\tfor i, column := range s.columns {\n\t\t\tif fullValueRaw, isAliased := catIndicesResponseRowAliasesMap[column]; isAliased {\n\t\t\t\t// alias can be translated to multiple fields,\n\t\t\t\t// so if translated value contains a comma, than replace the first value\n\t\t\t\t// and append the others\n\t\t\t\tif strings.Contains(fullValueRaw, \",\") {\n\t\t\t\t\tfullValues := strings.Split(fullValueRaw, \",\")\n\t\t\t\t\ts.columns[i] = fullValues[0]\n\t\t\t\t\ts.columns = append(s.columns, fullValues[1:]...)\n\t\t\t\t} else {\n\t\t\t\t\ts.columns[i] = fullValueRaw\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tparams.Set(\"h\", strings.Join(s.columns, \",\"))\n\t}\n\tif s.health != \"\" {\n\t\tparams.Set(\"health\", s.health)\n\t}\n\tif v := s.primaryOnly; v != nil {\n\t\tparams.Set(\"pri\", fmt.Sprint(*v))\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"s\", strings.Join(s.sort, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *CatIndicesService) Do(ctx context.Context) (CatIndicesResponse, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret CatIndicesResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// CatIndicesResponse is the outcome of CatIndicesService.Do.\ntype CatIndicesResponse []CatIndicesResponseRow\n\n// CatIndicesResponseRow specifies the data returned for one index\n// of a CatIndicesResponse. Notice that not all of these fields might\n// be filled; that depends on the number of columns chose in the\n// request (see CatIndicesService.Columns).\ntype CatIndicesResponseRow struct {\n\tHealth                       string `json:\"health\"`                              // \"green\", \"yellow\", or \"red\"\n\tStatus                       string `json:\"status\"`                              // \"open\" or \"closed\"\n\tIndex                        string `json:\"index\"`                               // index name\n\tUUID                         string `json:\"uuid\"`                                // index uuid\n\tPri                          int    `json:\"pri,string\"`                          // number of primary shards\n\tRep                          int    `json:\"rep,string\"`                          // number of replica shards\n\tDocsCount                    int    `json:\"docs.count,string\"`                   // number of available documents\n\tDocsDeleted                  int    `json:\"docs.deleted,string\"`                 // number of deleted documents\n\tCreationDate                 int64  `json:\"creation.date,string\"`                // index creation date (millisecond value), e.g. 1527077221644\n\tCreationDateString           string `json:\"creation.date.string\"`                // index creation date (as string), e.g. \"2018-05-23T12:07:01.644Z\"\n\tStoreSize                    string `json:\"store.size\"`                          // store size of primaries & replicas, e.g. \"4.6kb\"\n\tPriStoreSize                 string `json:\"pri.store.size\"`                      // store size of primaries, e.g. \"230b\"\n\tCompletionSize               string `json:\"completion.size\"`                     // size of completion on primaries & replicas\n\tPriCompletionSize            string `json:\"pri.completion.size\"`                 // size of completion on primaries\n\tFielddataMemorySize          string `json:\"fielddata.memory_size\"`               // used fielddata cache on primaries & replicas\n\tPriFielddataMemorySize       string `json:\"pri.fielddata.memory_size\"`           // used fielddata cache on primaries\n\tFielddataEvictions           int    `json:\"fielddata.evictions,string\"`          // fielddata evictions on primaries & replicas\n\tPriFielddataEvictions        int    `json:\"pri.fielddata.evictions,string\"`      // fielddata evictions on primaries\n\tQueryCacheMemorySize         string `json:\"query_cache.memory_size\"`             // used query cache on primaries & replicas\n\tPriQueryCacheMemorySize      string `json:\"pri.query_cache.memory_size\"`         // used query cache on primaries\n\tQueryCacheEvictions          int    `json:\"query_cache.evictions,string\"`        // query cache evictions on primaries & replicas\n\tPriQueryCacheEvictions       int    `json:\"pri.query_cache.evictions,string\"`    // query cache evictions on primaries\n\tRequestCacheMemorySize       string `json:\"request_cache.memory_size\"`           // used request cache on primaries & replicas\n\tPriRequestCacheMemorySize    string `json:\"pri.request_cache.memory_size\"`       // used request cache on primaries\n\tRequestCacheEvictions        int    `json:\"request_cache.evictions,string\"`      // request cache evictions on primaries & replicas\n\tPriRequestCacheEvictions     int    `json:\"pri.request_cache.evictions,string\"`  // request cache evictions on primaries\n\tRequestCacheHitCount         int    `json:\"request_cache.hit_count,string\"`      // request cache hit count on primaries & replicas\n\tPriRequestCacheHitCount      int    `json:\"pri.request_cache.hit_count,string\"`  // request cache hit count on primaries\n\tRequestCacheMissCount        int    `json:\"request_cache.miss_count,string\"`     // request cache miss count on primaries & replicas\n\tPriRequestCacheMissCount     int    `json:\"pri.request_cache.miss_count,string\"` // request cache miss count on primaries\n\tFlushTotal                   int    `json:\"flush.total,string\"`                  // number of flushes on primaries & replicas\n\tPriFlushTotal                int    `json:\"pri.flush.total,string\"`              // number of flushes on primaries\n\tFlushTotalTime               string `json:\"flush.total_time\"`                    // time spent in flush on primaries & replicas\n\tPriFlushTotalTime            string `json:\"pri.flush.total_time\"`                // time spent in flush on primaries\n\tGetCurrent                   int    `json:\"get.current,string\"`                  // number of current get ops on primaries & replicas\n\tPriGetCurrent                int    `json:\"pri.get.current,string\"`              // number of current get ops on primaries\n\tGetTime                      string `json:\"get.time\"`                            // time spent in get on primaries & replicas\n\tPriGetTime                   string `json:\"pri.get.time\"`                        // time spent in get on primaries\n\tGetTotal                     int    `json:\"get.total,string\"`                    // number of get ops on primaries & replicas\n\tPriGetTotal                  int    `json:\"pri.get.total,string\"`                // number of get ops on primaries\n\tGetExistsTime                string `json:\"get.exists_time\"`                     // time spent in successful gets on primaries & replicas\n\tPriGetExistsTime             string `json:\"pri.get.exists_time\"`                 // time spent in successful gets on primaries\n\tGetExistsTotal               int    `json:\"get.exists_total,string\"`             // number of successful gets on primaries & replicas\n\tPriGetExistsTotal            int    `json:\"pri.get.exists_total,string\"`         // number of successful gets on primaries\n\tGetMissingTime               string `json:\"get.missing_time\"`                    // time spent in failed gets on primaries & replicas\n\tPriGetMissingTime            string `json:\"pri.get.missing_time\"`                // time spent in failed gets on primaries\n\tGetMissingTotal              int    `json:\"get.missing_total,string\"`            // number of failed gets on primaries & replicas\n\tPriGetMissingTotal           int    `json:\"pri.get.missing_total,string\"`        // number of failed gets on primaries\n\tIndexingDeleteCurrent        int    `json:\"indexing.delete_current,string\"`      // number of current deletions on primaries & replicas\n\tPriIndexingDeleteCurrent     int    `json:\"pri.indexing.delete_current,string\"`  // number of current deletions on primaries\n\tIndexingDeleteTime           string `json:\"indexing.delete_time\"`                // time spent in deletions on primaries & replicas\n\tPriIndexingDeleteTime        string `json:\"pri.indexing.delete_time\"`            // time spent in deletions on primaries\n\tIndexingDeleteTotal          int    `json:\"indexing.delete_total,string\"`        // number of delete ops on primaries & replicas\n\tPriIndexingDeleteTotal       int    `json:\"pri.indexing.delete_total,string\"`    // number of delete ops on primaries\n\tIndexingIndexCurrent         int    `json:\"indexing.index_current,string\"`       // number of current indexing on primaries & replicas\n\tPriIndexingIndexCurrent      int    `json:\"pri.indexing.index_current,string\"`   // number of current indexing on primaries\n\tIndexingIndexTime            string `json:\"indexing.index_time\"`                 // time spent in indexing on primaries & replicas\n\tPriIndexingIndexTime         string `json:\"pri.indexing.index_time\"`             // time spent in indexing on primaries\n\tIndexingIndexTotal           int    `json:\"indexing.index_total,string\"`         // number of index ops on primaries & replicas\n\tPriIndexingIndexTotal        int    `json:\"pri.indexing.index_total,string\"`     // number of index ops on primaries\n\tIndexingIndexFailed          int    `json:\"indexing.index_failed,string\"`        // number of failed indexing ops on primaries & replicas\n\tPriIndexingIndexFailed       int    `json:\"pri.indexing.index_failed,string\"`    // number of failed indexing ops on primaries\n\tMergesCurrent                int    `json:\"merges.current,string\"`               // number of current merges on primaries & replicas\n\tPriMergesCurrent             int    `json:\"pri.merges.current,string\"`           // number of current merges on primaries\n\tMergesCurrentDocs            int    `json:\"merges.current_docs,string\"`          // number of current merging docs on primaries & replicas\n\tPriMergesCurrentDocs         int    `json:\"pri.merges.current_docs,string\"`      // number of current merging docs on primaries\n\tMergesCurrentSize            string `json:\"merges.current_size\"`                 // size of current merges on primaries & replicas\n\tPriMergesCurrentSize         string `json:\"pri.merges.current_size\"`             // size of current merges on primaries\n\tMergesTotal                  int    `json:\"merges.total,string\"`                 // number of completed merge ops on primaries & replicas\n\tPriMergesTotal               int    `json:\"pri.merges.total,string\"`             // number of completed merge ops on primaries\n\tMergesTotalDocs              int    `json:\"merges.total_docs,string\"`            // docs merged on primaries & replicas\n\tPriMergesTotalDocs           int    `json:\"pri.merges.total_docs,string\"`        // docs merged on primaries\n\tMergesTotalSize              string `json:\"merges.total_size\"`                   // size merged on primaries & replicas\n\tPriMergesTotalSize           string `json:\"pri.merges.total_size\"`               // size merged on primaries\n\tMergesTotalTime              string `json:\"merges.total_time\"`                   // time spent in merges on primaries & replicas\n\tPriMergesTotalTime           string `json:\"pri.merges.total_time\"`               // time spent in merges on primaries\n\tRefreshTotal                 int    `json:\"refresh.total,string\"`                // total refreshes on primaries & replicas\n\tPriRefreshTotal              int    `json:\"pri.refresh.total,string\"`            // total refreshes on primaries\n\tRefreshExternalTotal         int    `json:\"refresh.external_total,string\"`       // total external refreshes on primaries & replicas\n\tPriRefreshExternalTotal      int    `json:\"pri.refresh.external_total,string\"`   // total external refreshes on primaries\n\tRefreshTime                  string `json:\"refresh.time\"`                        // time spent in refreshes on primaries & replicas\n\tPriRefreshTime               string `json:\"pri.refresh.time\"`                    // time spent in refreshes on primaries\n\tRefreshExternalTime          string `json:\"refresh.external_time\"`               // external time spent in refreshes on primaries & replicas\n\tPriRefreshExternalTime       string `json:\"pri.refresh.external_time\"`           // external time spent in refreshes on primaries\n\tRefreshListeners             int    `json:\"refresh.listeners,string\"`            // number of pending refresh listeners on primaries & replicas\n\tPriRefreshListeners          int    `json:\"pri.refresh.listeners,string\"`        // number of pending refresh listeners on primaries\n\tSearchFetchCurrent           int    `json:\"search.fetch_current,string\"`         // current fetch phase ops on primaries & replicas\n\tPriSearchFetchCurrent        int    `json:\"pri.search.fetch_current,string\"`     // current fetch phase ops on primaries\n\tSearchFetchTime              string `json:\"search.fetch_time\"`                   // time spent in fetch phase on primaries & replicas\n\tPriSearchFetchTime           string `json:\"pri.search.fetch_time\"`               // time spent in fetch phase on primaries\n\tSearchFetchTotal             int    `json:\"search.fetch_total,string\"`           // total fetch ops on primaries & replicas\n\tPriSearchFetchTotal          int    `json:\"pri.search.fetch_total,string\"`       // total fetch ops on primaries\n\tSearchOpenContexts           int    `json:\"search.open_contexts,string\"`         // open search contexts on primaries & replicas\n\tPriSearchOpenContexts        int    `json:\"pri.search.open_contexts,string\"`     // open search contexts on primaries\n\tSearchQueryCurrent           int    `json:\"search.query_current,string\"`         // current query phase ops on primaries & replicas\n\tPriSearchQueryCurrent        int    `json:\"pri.search.query_current,string\"`     // current query phase ops on primaries\n\tSearchQueryTime              string `json:\"search.query_time\"`                   // time spent in query phase on primaries & replicas, e.g. \"0s\"\n\tPriSearchQueryTime           string `json:\"pri.search.query_time\"`               // time spent in query phase on primaries, e.g. \"0s\"\n\tSearchQueryTotal             int    `json:\"search.query_total,string\"`           // total query phase ops on primaries & replicas\n\tPriSearchQueryTotal          int    `json:\"pri.search.query_total,string\"`       // total query phase ops on primaries\n\tSearchScrollCurrent          int    `json:\"search.scroll_current,string\"`        // open scroll contexts on primaries & replicas\n\tPriSearchScrollCurrent       int    `json:\"pri.search.scroll_current,string\"`    // open scroll contexts on primaries\n\tSearchScrollTime             string `json:\"search.scroll_time\"`                  // time scroll contexts held open on primaries & replicas, e.g. \"0s\"\n\tPriSearchScrollTime          string `json:\"pri.search.scroll_time\"`              // time scroll contexts held open on primaries, e.g. \"0s\"\n\tSearchScrollTotal            int    `json:\"search.scroll_total,string\"`          // completed scroll contexts on primaries & replicas\n\tPriSearchScrollTotal         int    `json:\"pri.search.scroll_total,string\"`      // completed scroll contexts on primaries\n\tSearchThrottled              bool   `json:\"search.throttled,string\"`             // indicates if the index is search throttled\n\tSegmentsCount                int    `json:\"segments.count,string\"`               // number of segments on primaries & replicas\n\tPriSegmentsCount             int    `json:\"pri.segments.count,string\"`           // number of segments on primaries\n\tSegmentsMemory               string `json:\"segments.memory\"`                     // memory used by segments on primaries & replicas, e.g. \"1.3kb\"\n\tPriSegmentsMemory            string `json:\"pri.segments.memory\"`                 // memory used by segments on primaries, e.g. \"1.3kb\"\n\tSegmentsIndexWriterMemory    string `json:\"segments.index_writer_memory\"`        // memory used by index writer on primaries & replicas, e.g. \"0b\"\n\tPriSegmentsIndexWriterMemory string `json:\"pri.segments.index_writer_memory\"`    // memory used by index writer on primaries, e.g. \"0b\"\n\tSegmentsVersionMapMemory     string `json:\"segments.version_map_memory\"`         // memory used by version map on primaries & replicas, e.g. \"0b\"\n\tPriSegmentsVersionMapMemory  string `json:\"pri.segments.version_map_memory\"`     // memory used by version map on primaries, e.g. \"0b\"\n\tSegmentsFixedBitsetMemory    string `json:\"segments.fixed_bitset_memory\"`        // memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields on primaries & replicas, e.g. \"0b\"\n\tPriSegmentsFixedBitsetMemory string `json:\"pri.segments.fixed_bitset_memory\"`    // memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields on primaries, e.g. \"0b\"\n\tWarmerCurrent                int    `json:\"warmer.current,string\"`               // current warmer ops on primaries & replicas\n\tPriWarmerCurrent             int    `json:\"pri.warmer.current,string\"`           // current warmer ops on primaries\n\tWarmerTotal                  int    `json:\"warmer.total,string\"`                 // total warmer ops on primaries & replicas\n\tPriWarmerTotal               int    `json:\"pri.warmer.total,string\"`             // total warmer ops on primaries\n\tWarmerTotalTime              string `json:\"warmer.total_time\"`                   // time spent in warmers on primaries & replicas, e.g. \"47s\"\n\tPriWarmerTotalTime           string `json:\"pri.warmer.total_time\"`               // time spent in warmers on primaries, e.g. \"47s\"\n\tSuggestCurrent               int    `json:\"suggest.current,string\"`              // number of current suggest ops on primaries & replicas\n\tPriSuggestCurrent            int    `json:\"pri.suggest.current,string\"`          // number of current suggest ops on primaries\n\tSuggestTime                  string `json:\"suggest.time\"`                        // time spend in suggest on primaries & replicas, \"31s\"\n\tPriSuggestTime               string `json:\"pri.suggest.time\"`                    // time spend in suggest on primaries, e.g. \"31s\"\n\tSuggestTotal                 int    `json:\"suggest.total,string\"`                // number of suggest ops on primaries & replicas\n\tPriSuggestTotal              int    `json:\"pri.suggest.total,string\"`            // number of suggest ops on primaries\n\tMemoryTotal                  string `json:\"memory.total\"`                        // total user memory on primaries & replicas, e.g. \"1.5kb\"\n\tPriMemoryTotal               string `json:\"pri.memory.total\"`                    // total user memory on primaries, e.g. \"1.5kb\"\n}\n\n// catIndicesResponseRowAliasesMap holds the global map for columns aliases\n// the map is used by CatIndicesService.buildURL\n// for backwards compatibility some fields are able to have the same aliases\n// that means that one alias can be translated to different columns (from different elastic versions)\n// example for understanding: rto -> RefreshTotal, RefreshExternalTotal\nvar catIndicesResponseRowAliasesMap = map[string]string{\n\t\"qce\":                       \"query_cache.evictions\",\n\t\"searchFetchTime\":           \"search.fetch_time\",\n\t\"memoryTotal\":               \"memory.total\",\n\t\"requestCacheEvictions\":     \"request_cache.evictions\",\n\t\"ftt\":                       \"flush.total_time\",\n\t\"iic\":                       \"indexing.index_current\",\n\t\"mtt\":                       \"merges.total_time\",\n\t\"scti\":                      \"search.scroll_time\",\n\t\"searchScrollTime\":          \"search.scroll_time\",\n\t\"segmentsCount\":             \"segments.count\",\n\t\"getTotal\":                  \"get.total\",\n\t\"sfti\":                      \"search.fetch_time\",\n\t\"searchScrollCurrent\":       \"search.scroll_current\",\n\t\"svmm\":                      \"segments.version_map_memory\",\n\t\"warmerTotalTime\":           \"warmer.total_time\",\n\t\"r\":                         \"rep\",\n\t\"indexingIndexTime\":         \"indexing.index_time\",\n\t\"refreshTotal\":              \"refresh.total,refresh.external_total\",\n\t\"scc\":                       \"search.scroll_current\",\n\t\"suggestTime\":               \"suggest.time\",\n\t\"idc\":                       \"indexing.delete_current\",\n\t\"rti\":                       \"refresh.time,refresh.external_time\",\n\t\"sfto\":                      \"search.fetch_total\",\n\t\"completionSize\":            \"completion.size\",\n\t\"mt\":                        \"merges.total\",\n\t\"segmentsVersionMapMemory\":  \"segments.version_map_memory\",\n\t\"rto\":                       \"refresh.total,refresh.external_total\",\n\t\"id\":                        \"uuid\",\n\t\"dd\":                        \"docs.deleted\",\n\t\"docsDeleted\":               \"docs.deleted\",\n\t\"fielddataMemory\":           \"fielddata.memory_size\",\n\t\"getTime\":                   \"get.time\",\n\t\"getExistsTime\":             \"get.exists_time\",\n\t\"mtd\":                       \"merges.total_docs\",\n\t\"rli\":                       \"refresh.listeners\",\n\t\"h\":                         \"health\",\n\t\"cds\":                       \"creation.date.string\",\n\t\"rcmc\":                      \"request_cache.miss_count\",\n\t\"iif\":                       \"indexing.index_failed\",\n\t\"warmerCurrent\":             \"warmer.current\",\n\t\"gti\":                       \"get.time\",\n\t\"indexingIndexFailed\":       \"indexing.index_failed\",\n\t\"mts\":                       \"merges.total_size\",\n\t\"sqti\":                      \"search.query_time\",\n\t\"segmentsIndexWriterMemory\": \"segments.index_writer_memory\",\n\t\"iiti\":                      \"indexing.index_time\",\n\t\"iito\":                      \"indexing.index_total\",\n\t\"cd\":                        \"creation.date\",\n\t\"gc\":                        \"get.current\",\n\t\"searchFetchTotal\":          \"search.fetch_total\",\n\t\"sqc\":                       \"search.query_current\",\n\t\"segmentsMemory\":            \"segments.memory\",\n\t\"dc\":                        \"docs.count\",\n\t\"qcm\":                       \"query_cache.memory_size\",\n\t\"queryCacheMemory\":          \"query_cache.memory_size\",\n\t\"mergesTotalDocs\":           \"merges.total_docs\",\n\t\"searchOpenContexts\":        \"search.open_contexts\",\n\t\"shards.primary\":            \"pri\",\n\t\"cs\":                        \"completion.size\",\n\t\"mergesTotalTIme\":           \"merges.total_time\",\n\t\"wtt\":                       \"warmer.total_time\",\n\t\"mergesCurrentSize\":         \"merges.current_size\",\n\t\"mergesTotal\":               \"merges.total\",\n\t\"refreshTime\":               \"refresh.time,refresh.external_time\",\n\t\"wc\":                        \"warmer.current\",\n\t\"p\":                         \"pri\",\n\t\"idti\":                      \"indexing.delete_time\",\n\t\"searchQueryCurrent\":        \"search.query_current\",\n\t\"warmerTotal\":               \"warmer.total\",\n\t\"suggestTotal\":              \"suggest.total\",\n\t\"tm\":                        \"memory.total\",\n\t\"ss\":                        \"store.size\",\n\t\"ft\":                        \"flush.total\",\n\t\"getExistsTotal\":            \"get.exists_total\",\n\t\"scto\":                      \"search.scroll_total\",\n\t\"s\":                         \"status\",\n\t\"queryCacheEvictions\":       \"query_cache.evictions\",\n\t\"rce\":                       \"request_cache.evictions\",\n\t\"geto\":                      \"get.exists_total\",\n\t\"refreshListeners\":          \"refresh.listeners\",\n\t\"suto\":                      \"suggest.total\",\n\t\"storeSize\":                 \"store.size\",\n\t\"gmti\":                      \"get.missing_time\",\n\t\"indexingIdexCurrent\":       \"indexing.index_current\",\n\t\"searchFetchCurrent\":        \"search.fetch_current\",\n\t\"idx\":                       \"index\",\n\t\"fm\":                        \"fielddata.memory_size\",\n\t\"geti\":                      \"get.exists_time\",\n\t\"indexingDeleteCurrent\":     \"indexing.delete_current\",\n\t\"mergesCurrentDocs\":         \"merges.current_docs\",\n\t\"sth\":                       \"search.throttled\",\n\t\"flushTotal\":                \"flush.total\",\n\t\"sfc\":                       \"search.fetch_current\",\n\t\"wto\":                       \"warmer.total\",\n\t\"suti\":                      \"suggest.time\",\n\t\"shardsReplica\":             \"rep\",\n\t\"mergesCurrent\":             \"merges.current\",\n\t\"mcs\":                       \"merges.current_size\",\n\t\"so\":                        \"search.open_contexts\",\n\t\"i\":                         \"index\",\n\t\"siwm\":                      \"segments.index_writer_memory\",\n\t\"sfbm\":                      \"segments.fixed_bitset_memory\",\n\t\"fe\":                        \"fielddata.evictions\",\n\t\"requestCacheMissCount\":     \"request_cache.miss_count\",\n\t\"idto\":                      \"indexing.delete_total\",\n\t\"mergesTotalSize\":           \"merges.total_size\",\n\t\"suc\":                       \"suggest.current\",\n\t\"suggestCurrent\":            \"suggest.current\",\n\t\"flushTotalTime\":            \"flush.total_time\",\n\t\"getMissingTotal\":           \"get.missing_total\",\n\t\"sqto\":                      \"search.query_total\",\n\t\"searchScrollTotal\":         \"search.scroll_total\",\n\t\"fixedBitsetMemory\":         \"segments.fixed_bitset_memory\",\n\t\"getMissingTime\":            \"get.missing_time\",\n\t\"indexingDeleteTotal\":       \"indexing.delete_total\",\n\t\"mcd\":                       \"merges.current_docs\",\n\t\"docsCount\":                 \"docs.count\",\n\t\"gto\":                       \"get.total\",\n\t\"mc\":                        \"merges.current\",\n\t\"fielddataEvictions\":        \"fielddata.evictions\",\n\t\"rcm\":                       \"request_cache.memory_size\",\n\t\"requestCacheHitCount\":      \"request_cache.hit_count\",\n\t\"gmto\":                      \"get.missing_total\",\n\t\"searchQueryTime\":           \"search.query_time\",\n\t\"shards.replica\":            \"rep\",\n\t\"requestCacheMemory\":        \"request_cache.memory_size\",\n\t\"rchc\":                      \"request_cache.hit_count\",\n\t\"getCurrent\":                \"get.current\",\n\t\"indexingIndexTotal\":        \"indexing.index_total\",\n\t\"sc\":                        \"segments.count,segments.memory\",\n\t\"shardsPrimary\":             \"pri\",\n\t\"indexingDeleteTime\":        \"indexing.delete_time\",\n\t\"searchQueryTotal\":          \"search.query_total\",\n}\n"
  },
  {
    "path": "cat_indices_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCatIndices(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\tres, err := client.CatIndices().Columns(\"*\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\tif have := res[0].Index; have == \"\" {\n\t\tt.Fatalf(\"Index[0]: want != %q, have %q\", \"\", have)\n\t}\n}\n\n// TestCatIndicesResponseRowAliasesMap tests if catIndicesResponseRowAliasesMap is declared\nfunc TestCatIndicesResponseRowAliasesMap(t *testing.T) {\n\tif catIndicesResponseRowAliasesMap == nil {\n\t\tt.Fatal(\"want catIndicesResponseRowAliasesMap to be not nil\")\n\t}\n\n\tif len(catIndicesResponseRowAliasesMap) == 0 {\n\t\tt.Fatal(\"want catIndicesResponseRowAliasesMap to be not empty\")\n\t}\n}\n\n// TestCatIndicesWithAliases makes a simple test (if ?h=h will be the same as ?h=health)\nfunc TestCatIndicesWithAliases(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\tres, err := client.CatIndices().Columns(\"h\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\tif have := res[0].Health; have == \"\" {\n\t\tt.Fatalf(\"Index[0]: want != %q, have %q\", \"\", have)\n\t}\n}\n\n// TestCatIndicesWithAliases makes a test with a double-alias\n// asking `?h=rti` will fill one of the refresh.external_time/refresh.time fields (depending on elasticsearch version)\nfunc TestCatIndicesWithAliases_Double(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\tres, err := client.CatIndices().Columns(\"rti\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\n\trefreshTime := res[0].RefreshTime\n\trefreshExternalTime := res[0].RefreshExternalTime\n\n\tif refreshTime == \"\" && refreshExternalTime == \"\" {\n\t\tt.Fatalf(\"Index[0]: want one of [refreshTime or refreshExternalTime] be not empty\")\n\t}\n}\n"
  },
  {
    "path": "cat_master.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// CatMasterService shows information about the master node,\n// including the ID, bound IP address, and name.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.12/cat-master.html\n// for details.\ntype CatMasterService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tlocal         *bool\n\tmasterTimeout string\n\tcolumns       []string\n\tsort          []string // list of columns for sort order\n}\n\n// NewCatMasterService creates a new CatMasterService\nfunc NewCatMasterService(client *Client) *CatMasterService {\n\treturn &CatMasterService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CatMasterService) Pretty(pretty bool) *CatMasterService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CatMasterService) Human(human bool) *CatMasterService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CatMasterService) ErrorTrace(errorTrace bool) *CatMasterService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CatMasterService) FilterPath(filterPath ...string) *CatMasterService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CatMasterService) Header(name string, value string) *CatMasterService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CatMasterService) Headers(headers http.Header) *CatMasterService {\n\ts.headers = headers\n\treturn s\n}\n\n// Local indicates to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *CatMasterService) Local(local bool) *CatMasterService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout is the explicit operation timeout for connection to master node.\nfunc (s *CatMasterService) MasterTimeout(masterTimeout string) *CatMasterService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Columns to return in the response.\n// To get a list of all possible columns to return, run the following command\n// in your terminal:\n//\n// Example:\n//   curl 'http://localhost:9200/_cat/master?help'\n//\n// You can use Columns(\"*\") to return all possible columns. That might take\n// a little longer than the default set of columns.\nfunc (s *CatMasterService) Columns(columns ...string) *CatMasterService {\n\ts.columns = columns\n\treturn s\n}\n\n// Sort is a list of fields to sort by.\nfunc (s *CatMasterService) Sort(fields ...string) *CatMasterService {\n\ts.sort = fields\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *CatMasterService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath := \"/_cat/master\"\n\n\t// Add query string parameters\n\tparams := url.Values{\n\t\t\"format\": []string{\"json\"}, // always returns as JSON\n\t}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"s\", strings.Join(s.sort, \",\"))\n\t}\n\tif len(s.columns) > 0 {\n\t\tparams.Set(\"h\", strings.Join(s.columns, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *CatMasterService) Do(ctx context.Context) (CatMasterResponse, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret CatMasterResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// CatMasterResponse is the outcome of CatMasterService.Do.\ntype CatMasterResponse []CatMasterResponseRow\n\n// CatMasterResponseRow is a single row in a CatMasterResponse.\n// Notice that not all of these fields might be filled; that depends\n// on the number of columns chose in the request (see CatMasterService.Columns).\ntype CatMasterResponseRow struct {\n\tID   string `json:\"id\"`\n\tHost string `json:\"host\"`\n\tIP   string `json:\"ip\"`\n\tNode string `json:\"node\"`\n}\n"
  },
  {
    "path": "cat_master_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCatMaster(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tctx := context.Background()\n\tres, err := client.CatMaster().Columns(\"*\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\tif have := res[0].IP; have == \"\" {\n\t\tt.Fatalf(\"IP[0]: want != %q, have %q\", \"\", have)\n\t}\n}\n"
  },
  {
    "path": "cat_shards.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// CatShardsService returns the list of shards plus some additional\n// information about them.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.6/cat-shards.html\n// for details.\ntype CatShardsService struct {\n\tclient *Client\n\n\tpretty     *bool    // pretty format the returned JSON response\n\thuman      *bool    // return human readable values for statistics\n\terrorTrace *bool    // include the stack trace of returned errors\n\tfilterPath []string // list of filters used to reduce the response\n\n\tindex         []string\n\tbytes         string // b, k, kb, m, mb, g, gb, t, tb, p, or pb\n\tlocal         *bool\n\tmasterTimeout string\n\tcolumns       []string\n\ttime          string   // d, h, m, s, ms, micros, or nanos\n\tsort          []string // list of columns for sort order\n\theaders       http.Header\n}\n\n// NewCatShardsService creates a new CatShardsService.\nfunc NewCatShardsService(client *Client) *CatShardsService {\n\treturn &CatShardsService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CatShardsService) Pretty(pretty bool) *CatShardsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CatShardsService) Human(human bool) *CatShardsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CatShardsService) ErrorTrace(errorTrace bool) *CatShardsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CatShardsService) FilterPath(filterPath ...string) *CatShardsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CatShardsService) Header(name string, value string) *CatShardsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CatShardsService) Headers(headers http.Header) *CatShardsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the index to list (by default all indices are returned).\nfunc (s *CatShardsService) Index(index ...string) *CatShardsService {\n\ts.index = index\n\treturn s\n}\n\n// Bytes represents the unit in which to display byte values.\n// Valid values are: \"b\", \"k\", \"kb\", \"m\", \"mb\", \"g\", \"gb\", \"t\", \"tb\", \"p\" or \"pb\".\nfunc (s *CatShardsService) Bytes(bytes string) *CatShardsService {\n\ts.bytes = bytes\n\treturn s\n}\n\n// Local indicates to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *CatShardsService) Local(local bool) *CatShardsService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout is the explicit operation timeout for connection to master node.\nfunc (s *CatShardsService) MasterTimeout(masterTimeout string) *CatShardsService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Columns to return in the response.\n//\n// To get a list of all possible columns to return, run the following command\n// in your terminal:\n//\n// Example:\n//   curl 'http://localhost:9200/_cat/shards?help'\n//\n// You can use Columns(\"*\") to return all possible columns. That might take\n// a little longer than the default set of columns.\nfunc (s *CatShardsService) Columns(columns ...string) *CatShardsService {\n\ts.columns = columns\n\treturn s\n}\n\n// Sort is a list of fields to sort by.\nfunc (s *CatShardsService) Sort(fields ...string) *CatShardsService {\n\ts.sort = fields\n\treturn s\n}\n\n// Time specifies the way that time values are formatted with.\nfunc (s *CatShardsService) Time(time string) *CatShardsService {\n\ts.time = time\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *CatShardsService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_cat/shards/{index}\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_cat/shards\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{\n\t\t\"format\": []string{\"json\"}, // always returns as JSON\n\t}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.bytes != \"\" {\n\t\tparams.Set(\"bytes\", s.bytes)\n\t}\n\tif s.time != \"\" {\n\t\tparams.Set(\"time\", s.time)\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif len(s.columns) > 0 {\n\t\t// loop through all columns and apply alias if needed\n\t\tfor i, column := range s.columns {\n\t\t\tif fullValueRaw, isAliased := catShardsResponseRowAliasesMap[column]; isAliased {\n\t\t\t\t// alias can be translated to multiple fields,\n\t\t\t\t// so if translated value contains a comma, than replace the first value\n\t\t\t\t// and append the others\n\t\t\t\tif strings.Contains(fullValueRaw, \",\") {\n\t\t\t\t\tfullValues := strings.Split(fullValueRaw, \",\")\n\t\t\t\t\ts.columns[i] = fullValues[0]\n\t\t\t\t\ts.columns = append(s.columns, fullValues[1:]...)\n\t\t\t\t} else {\n\t\t\t\t\ts.columns[i] = fullValueRaw\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tparams.Set(\"h\", strings.Join(s.columns, \",\"))\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"s\", strings.Join(s.sort, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *CatShardsService) Do(ctx context.Context) (CatShardsResponse, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret CatShardsResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// CatShardsResponse is the outcome of CatShardsService.Do.\ntype CatShardsResponse []CatShardsResponseRow\n\n// CatShardsResponseRow specifies the data returned for one index\n// of a CatShardsResponse. Notice that not all of these fields might\n// be filled; that depends on the number of columns chose in the\n// request (see CatShardsService.Columns).\ntype CatShardsResponseRow struct {\n\tIndex                     string `json:\"index\"`        // index name\n\tUUID                      string `json:\"uuid\"`         // index uuid\n\tShard                     int    `json:\"shard,string\"` // shard number, e.g. 1\n\tPrirep                    string `json:\"prirep\"`       // \"r\" for replica, \"p\" for primary\n\tState                     string `json:\"state\"`        // STARTED, INITIALIZING, RELOCATING, or UNASSIGNED\n\tDocs                      int64  `json:\"docs,string\"`  // number of documents, e.g. 142847\n\tStore                     string `json:\"store\"`        // size, e.g. \"40mb\"\n\tIP                        string `json:\"ip\"`           // IP address\n\tID                        string `json:\"id\"`\n\tNode                      string `json:\"node\"` // Node name\n\tSyncID                    string `json:\"sync_id\"`\n\tUnassignedReason          string `json:\"unassigned.reason\"`\n\tUnassignedAt              string `json:\"unassigned.at\"`\n\tUnassignedFor             string `json:\"unassigned.for\"`\n\tUnassignedDetails         string `json:\"unassigned.details\"`\n\tRecoverysourceType        string `json:\"recoverysource.type\"`\n\tCompletionSize            string `json:\"completion.size\"`                // size of completion on primaries & replicas\n\tFielddataMemorySize       string `json:\"fielddata.memory_size\"`          // used fielddata cache on primaries & replicas\n\tFielddataEvictions        int    `json:\"fielddata.evictions,string\"`     // fielddata evictions on primaries & replicas\n\tQueryCacheMemorySize      string `json:\"query_cache.memory_size\"`        // used query cache on primaries & replicas\n\tQueryCacheEvictions       int    `json:\"query_cache.evictions,string\"`   // query cache evictions on primaries & replicas\n\tFlushTotal                int    `json:\"flush.total,string\"`             // number of flushes on primaries & replicas\n\tFlushTotalTime            string `json:\"flush.total_time\"`               // time spent in flush on primaries & replicas\n\tGetCurrent                int    `json:\"get.current,string\"`             // number of current get ops on primaries & replicas\n\tGetTime                   string `json:\"get.time\"`                       // time spent in get on primaries & replicas\n\tGetTotal                  int    `json:\"get.total,string\"`               // number of get ops on primaries & replicas\n\tGetExistsTime             string `json:\"get.exists_time\"`                // time spent in successful gets on primaries & replicas\n\tGetExistsTotal            int    `json:\"get.exists_total,string\"`        // number of successful gets on primaries & replicas\n\tGetMissingTime            string `json:\"get.missing_time\"`               // time spent in failed gets on primaries & replicas\n\tGetMissingTotal           int    `json:\"get.missing_total,string\"`       // number of failed gets on primaries & replicas\n\tIndexingDeleteCurrent     int    `json:\"indexing.delete_current,string\"` // number of current deletions on primaries & replicas\n\tIndexingDeleteTime        string `json:\"indexing.delete_time\"`           // time spent in deletions on primaries & replicas\n\tIndexingDeleteTotal       int    `json:\"indexing.delete_total,string\"`   // number of delete ops on primaries & replicas\n\tIndexingIndexCurrent      int    `json:\"indexing.index_current,string\"`  // number of current indexing on primaries & replicas\n\tIndexingIndexTime         string `json:\"indexing.index_time\"`            // time spent in indexing on primaries & replicas\n\tIndexingIndexTotal        int    `json:\"indexing.index_total,string\"`    // number of index ops on primaries & replicas\n\tIndexingIndexFailed       int    `json:\"indexing.index_failed,string\"`   // number of failed indexing ops on primaries & replicas\n\tMergesCurrent             int    `json:\"merges.current,string\"`          // number of current merges on primaries & replicas\n\tMergesCurrentDocs         int    `json:\"merges.current_docs,string\"`     // number of current merging docs on primaries & replicas\n\tMergesCurrentSize         string `json:\"merges.current_size\"`            // size of current merges on primaries & replicas\n\tMergesTotal               int    `json:\"merges.total,string\"`            // number of completed merge ops on primaries & replicas\n\tMergesTotalDocs           int    `json:\"merges.total_docs,string\"`       // docs merged on primaries & replicas\n\tMergesTotalSize           string `json:\"merges.total_size\"`              // size merged on primaries & replicas\n\tMergesTotalTime           string `json:\"merges.total_time\"`              // time spent in merges on primaries & replicas\n\tRefreshTotal              int    `json:\"refresh.total,string\"`           // total refreshes on primaries & replicas\n\tRefreshExternalTotal      int    `json:\"refresh.external_total,string\"`  // total external refreshes on primaries & replicas\n\tRefreshTime               string `json:\"refresh.time\"`                   // time spent in refreshes on primaries & replicas\n\tRefreshExternalTime       string `json:\"refresh.external_time\"`          // external time spent in refreshes on primaries & replicas\n\tRefreshListeners          int    `json:\"refresh.listeners,string\"`       // number of pending refresh listeners on primaries & replicas\n\tSearchFetchCurrent        int    `json:\"search.fetch_current,string\"`    // current fetch phase ops on primaries & replicas\n\tSearchFetchTime           string `json:\"search.fetch_time\"`              // time spent in fetch phase on primaries & replicas\n\tSearchFetchTotal          int    `json:\"search.fetch_total,string\"`      // total fetch ops on primaries & replicas\n\tSearchOpenContexts        int    `json:\"search.open_contexts,string\"`    // open search contexts on primaries & replicas\n\tSearchQueryCurrent        int    `json:\"search.query_current,string\"`    // current query phase ops on primaries & replicas\n\tSearchQueryTime           string `json:\"search.query_time\"`              // time spent in query phase on primaries & replicas, e.g. \"0s\"\n\tSearchQueryTotal          int    `json:\"search.query_total,string\"`      // total query phase ops on primaries & replicas\n\tSearchScrollCurrent       int    `json:\"search.scroll_current,string\"`   // open scroll contexts on primaries & replicas\n\tSearchScrollTime          string `json:\"search.scroll_time\"`             // time scroll contexts held open on primaries & replicas, e.g. \"0s\"\n\tSearchScrollTotal         int    `json:\"search.scroll_total,string\"`     // completed scroll contexts on primaries & replicas\n\tSearchThrottled           bool   `json:\"search.throttled,string\"`        // indicates if the index is search throttled\n\tSegmentsCount             int    `json:\"segments.count,string\"`          // number of segments on primaries & replicas\n\tSegmentsMemory            string `json:\"segments.memory\"`                // memory used by segments on primaries & replicas, e.g. \"1.3kb\"\n\tSegmentsIndexWriterMemory string `json:\"segments.index_writer_memory\"`   // memory used by index writer on primaries & replicas, e.g. \"0b\"\n\tSegmentsVersionMapMemory  string `json:\"segments.version_map_memory\"`    // memory used by version map on primaries & replicas, e.g. \"0b\"\n\tSegmentsFixedBitsetMemory string `json:\"segments.fixed_bitset_memory\"`   // memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields on primaries & replicas, e.g. \"0b\"\n\tSeqNoMax                  int    `json:\"seq_no.max,string\"`\n\tSeqNoLocalCheckpoint      int    `json:\"seq_no.local_checkpoint,string\"`\n\tSeqNoGlobalCheckpoint     int    `json:\"seq_no.global_checkpoint,string\"`\n\tWarmerCurrent             int    `json:\"warmer.current,string\"` // current warmer ops on primaries & replicas\n\tWarmerTotal               int    `json:\"warmer.total,string\"`   // total warmer ops on primaries & replicas\n\tWarmerTotalTime           string `json:\"warmer.total_time\"`     // time spent in warmers on primaries & replicas, e.g. \"47s\"\n\tPathData                  string `json:\"path.data\"`\n\tPathState                 string `json:\"path.state\"`\n}\n\n// catShardsResponseRowAliasesMap holds the global map for columns aliases\n// the map is used by CatShardsService.buildURL.\n// For backwards compatibility some fields are able to have the same aliases\n// that means that one alias can be translated to different columns (from different elastic versions)\n// example for understanding: rto -> RefreshTotal, RefreshExternalTotal\nvar catShardsResponseRowAliasesMap = map[string]string{\n\t\"sync_id\": \"sync_id\",\n\t\"ur\":      \"unassigned.reason\",\n\t\"ua\":      \"unassigned.at\",\n\t\"uf\":      \"unassigned.for\",\n\t\"ud\":      \"unassigned.details\",\n\t\"rs\":      \"recoverysource.type\",\n\t\"cs\":      \"completion.size\",\n\t\"fm\":      \"fielddata.memory_size\",\n\t\"fe\":      \"fielddata.evictions\",\n\t\"qcm\":     \"query_cache.memory_size\",\n\t\"qce\":     \"query_cache.evictions\",\n\t\"ft\":      \"flush.total\",\n\t\"ftt\":     \"flush.total_time\",\n\t\"gc\":      \"get.current\",\n\t\"gti\":     \"get.time\",\n\t\"gto\":     \"get.total\",\n\t\"geti\":    \"get.exists_time\",\n\t\"geto\":    \"get.exists_total\",\n\t\"gmti\":    \"get.missing_time\",\n\t\"gmto\":    \"get.missing_total\",\n\t\"idc\":     \"indexing.delete_current\",\n\t\"idti\":    \"indexing.delete_time\",\n\t\"idto\":    \"indexing.delete_total\",\n\t\"iic\":     \"indexing.index_current\",\n\t\"iiti\":    \"indexing.index_time\",\n\t\"iito\":    \"indexing.index_total\",\n\t\"iif\":     \"indexing.index_failed\",\n\t\"mc\":      \"merges.current\",\n\t\"mcd\":     \"merges.current_docs\",\n\t\"mcs\":     \"merges.current_size\",\n\t\"mt\":      \"merges.total\",\n\t\"mtd\":     \"merges.total_docs\",\n\t\"mts\":     \"merges.total_size\",\n\t\"mtt\":     \"merges.total_time\",\n\t\"rto\":     \"refresh.total\",\n\t\"rti\":     \"refresh.time\",\n\t// \"rto\":     \"refresh.external_total\",\n\t// \"rti\":     \"refresh.external_time\",\n\t\"rli\":  \"refresh.listeners\",\n\t\"sfc\":  \"search.fetch_current\",\n\t\"sfti\": \"search.fetch_time\",\n\t\"sfto\": \"search.fetch_total\",\n\t\"so\":   \"search.open_contexts\",\n\t\"sqc\":  \"search.query_current\",\n\t\"sqti\": \"search.query_time\",\n\t\"sqto\": \"search.query_total\",\n\t\"scc\":  \"search.scroll_current\",\n\t\"scti\": \"search.scroll_time\",\n\t\"scto\": \"search.scroll_total\",\n\t\"sc\":   \"segments.count\",\n\t\"sm\":   \"segments.memory\",\n\t\"siwm\": \"segments.index_writer_memory\",\n\t\"svmm\": \"segments.version_map_memory\",\n\t\"sfbm\": \"segments.fixed_bitset_memory\",\n\t\"sqm\":  \"seq_no.max\",\n\t\"sql\":  \"seq_no.local_checkpoint\",\n\t\"sqg\":  \"seq_no.global_checkpoint\",\n\t\"wc\":   \"warmer.current\",\n\t\"wto\":  \"warmer.total\",\n\t\"wtt\":  \"warmer.total_time\",\n}\n"
  },
  {
    "path": "cat_shards_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCatShards(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\tres, err := client.CatShards().Columns(\"*\").Pretty(true).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\tif have := res[0].Index; have == \"\" {\n\t\tt.Fatalf(\"Index[0]: want != %q, have %q\", \"\", have)\n\t}\n}\n\n// TestCatShardsResponseRowAliasesMap tests if catIndicesResponseRowAliasesMap is declared\nfunc TestCatShardsResponseRowAliasesMap(t *testing.T) {\n\tif catIndicesResponseRowAliasesMap == nil {\n\t\tt.Fatal(\"want catIndicesResponseRowAliasesMap to be not nil\")\n\t}\n\tif len(catIndicesResponseRowAliasesMap) == 0 {\n\t\tt.Fatal(\"want catIndicesResponseRowAliasesMap to be not empty\")\n\t}\n}\n\n// TestCatShardsWithSpecificColumns makes a simple test with specific column names.\nfunc TestCatShardsWithSpecificColumns(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tctx := context.Background()\n\tres, err := client.CatShards().Columns(\"index\", \"shard\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif len(res) == 0 {\n\t\tt.Fatalf(\"want response, have: %v\", res)\n\t}\n\tif have := res[0].Index; have == \"\" {\n\t\tt.Fatalf(\"Index[0]: want != %q, have %q\", \"\", have)\n\t}\n}\n"
  },
  {
    "path": "cat_snapshots.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// CatSnapshotsService returns the list of snapshots.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.13/cat-snapshots.html\n// for details.\ntype CatSnapshotsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository    string // snapshot repository used to limit the request\n\tmasterTimeout string\n\tcolumns       []string\n\tsort          []string // list of columns for sort order\n}\n\n// NewCatSnapshotsService creates a new NewCatSnapshotsService.\nfunc NewCatSnapshotsService(client *Client) *CatSnapshotsService {\n\treturn &CatSnapshotsService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CatSnapshotsService) Pretty(pretty bool) *CatSnapshotsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CatSnapshotsService) Human(human bool) *CatSnapshotsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CatSnapshotsService) ErrorTrace(errorTrace bool) *CatSnapshotsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CatSnapshotsService) FilterPath(filterPath ...string) *CatSnapshotsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CatSnapshotsService) Header(name string, value string) *CatSnapshotsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CatSnapshotsService) Headers(headers http.Header) *CatSnapshotsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository specifies the napshot repository used to limit the request.\nfunc (s *CatSnapshotsService) Repository(repository string) *CatSnapshotsService {\n\ts.repository = repository\n\treturn s\n}\n\n// MasterTimeout is the explicit operation timeout for connection to master node.\nfunc (s *CatSnapshotsService) MasterTimeout(masterTimeout string) *CatSnapshotsService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Columns to return in the response.\n// To get a list of all possible columns to return, run the following command\n// in your terminal:\n//\n// Example:\n//   curl 'http://localhost:9200/_cat/snapshots/<repository>?help'\n//\n// You can use Columns(\"*\") to return all possible columns. That might take\n// a little longer than the default set of columns.\nfunc (s *CatSnapshotsService) Columns(columns ...string) *CatSnapshotsService {\n\ts.columns = columns\n\treturn s\n}\n\n// Sort is a list of fields to sort by.\nfunc (s *CatSnapshotsService) Sort(fields ...string) *CatSnapshotsService {\n\ts.sort = fields\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *CatSnapshotsService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\n\tif s.repository != \"\" {\n\t\tpath, err = uritemplates.Expand(\"/_cat/snapshots/{repository}\", map[string]string{\n\t\t\t\"repository\": s.repository,\n\t\t})\n\t} else {\n\t\tpath = \"/_cat/snapshots\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{\n\t\t\"format\": []string{\"json\"}, // always returns as JSON\n\t}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\t// TODO\n\tif len(s.columns) > 0 {\n\t\t// loop through all columns and apply alias if needed\n\t\tfor i, column := range s.columns {\n\t\t\tif fullValueRaw, isAliased := catSnapshotsResponseRowAliasesMap[column]; isAliased {\n\t\t\t\t// alias can be translated to multiple fields,\n\t\t\t\t// so if translated value contains a comma, than replace the first value\n\t\t\t\t// and append the others\n\t\t\t\tif strings.Contains(fullValueRaw, \",\") {\n\t\t\t\t\tfullValues := strings.Split(fullValueRaw, \",\")\n\t\t\t\t\ts.columns[i] = fullValues[0]\n\t\t\t\t\ts.columns = append(s.columns, fullValues[1:]...)\n\t\t\t\t} else {\n\t\t\t\t\ts.columns[i] = fullValueRaw\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tparams.Set(\"h\", strings.Join(s.columns, \",\"))\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"s\", strings.Join(s.sort, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *CatSnapshotsService) Do(ctx context.Context) (CatSnapshotsResponse, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret CatSnapshotsResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// CatSnapshotsResponse is the outcome of CatSnapshotsService.Do.\ntype CatSnapshotsResponse []CatSnapshotsResponseRow\n\n// CatSnapshotssResponseRow specifies the data returned for one index\n// of a CatSnapshotsResponse. Notice that not all of these fields might\n// be filled; that depends on the number of columns chose in the\n// request (see CatSnapshotsService.Columns).\ntype CatSnapshotsResponseRow struct {\n\tID               string `json:\"id\"`                // ID of the snapshot, such as \"snap1\".\n\tRepository       string `json:\"repository\"`        // Name of the repository, such as \"repo1\".\n\tStatus           string `json:\"status\"`            // One of \"FAILED\", \"INCOMPATIBLE\", \"IN_PROGRESS\", \"PARTIAL\" or \"SUCCESS\".\n\tStartEpoch       string `json:\"start_epoch\"`       // Unix epoch time at which the snapshot process started.\n\tStartTime        string `json:\"start_time\"`        // HH:MM:SS time at which the snapshot process started.\n\tEndEpoch         string `json:\"end_epoch\"`         // Unix epoch time at which the snapshot process ended.\n\tEndTime          string `json:\"end_time\"`          // HH:MM:SS time at which the snapshot process ended.\n\tDuration         string `json:\"duration\"`          // Time it took the snapshot process to complete in time units.\n\tIndices          string `json:\"indices\"`           // Number of indices in the snapshot.\n\tSuccessfulShards string `json:\"successful_shards\"` // Number of successful shards in the snapshot.\n\tFailedShards     string `json:\"failed_shards\"`     // Number of failed shards in the snapshot.\n\tTotalShards      string `json:\"total_shards\"`      // Total number of shards in the snapshot.\n\tReason           string `json:\"reason\"`            // Reason for any snapshot failures.\n}\n\n// catSnapshotsResponseRowAliasesMap holds the global map for columns aliases\n// the map is used by CatSnapshotsService.buildURL.\n// For backwards compatibility some fields are able to have the same aliases\n// that means that one alias can be translated to different columns (from different elastic versions)\n// example for understanding: rto -> RefreshTotal, RefreshExternalTotal\nvar catSnapshotsResponseRowAliasesMap = map[string]string{\n\t\"snapshot\": \"id\",\n\t\"re\":       \"repository\",\n\t\"s\":        \"status\",\n\t\"ste\":      \"start_epoch\",\n\t\"sti\":      \"start_time\",\n\t\"ete\":      \"end_epoch\",\n\t\"eti\":      \"end_time\",\n\t\"dur\":      \"duration\",\n\t\"i\":        \"indices\",\n\t\"ss\":       \"successful_shards\",\n\t\"fs\":       \"failed_shards\",\n\t\"ts\":       \"total_shards\",\n\t\"`r\":       \"reason\",\n}\n"
  },
  {
    "path": "cat_snapshots_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestCatSnapshotsIntegration(t *testing.T) {\n\tif isCI() {\n\t\tt.Skip(\"this test requires local directories\")\n\t}\n\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t{\n\t\t// Create a repository for this test\n\t\tctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)\n\t\tdefer cancel()\n\t\t_, err := client.SnapshotCreateRepository(\"my_backup\").\n\t\t\tType(\"fs\").\n\t\t\tSettings(map[string]interface{}{\n\t\t\t\t// Notice the path is configured as path.repo in docker-compose.yml\n\t\t\t\t\"location\": \"/usr/share/elasticsearch/backup\",\n\t\t\t}).\n\t\t\tDo(ctx)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\t// Make a snapshot\n\t\tctx, cancel = context.WithTimeout(context.Background(), 15*time.Second)\n\t\tdefer cancel()\n\t\t_, err = client.SnapshotCreate(\"my_backup\", \"snapshot_1\").\n\t\t\tWaitForCompletion(true).\n\t\t\tDo(ctx)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\n\t\tdefer func() {\n\t\t\t// Remove snapshot\n\t\t\t_, _ = client.SnapshotDelete(\"my_backup\", \"snapshot_1\").Do(context.Background())\n\t\t\t// Remove repository\n\t\t\t_, _ = client.SnapshotDeleteRepository(\"my_backup\").Do(context.Background())\n\t\t}()\n\t}\n\n\t// List snapshots of repository\n\tctx := context.Background()\n\tres, err := client.CatSnapshots().Repository(\"my_backup\").Columns(\"*\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"want response, have nil\")\n\t}\n\tif want, have := 1, len(res); want != have {\n\t\tt.Fatalf(\"want %d snapshot, have %d\", want, have)\n\t}\n\tif want, have := \"snapshot_1\", res[0].ID; want != have {\n\t\tt.Fatalf(\"want ID=%q, have %q\", want, have)\n\t}\n}\n"
  },
  {
    "path": "cat_snapshots_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestCatSnapshots(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetDecoder(&strictDecoder{})) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\turls, params, err := client.CatSnapshots().Repository(\"my_repo\").Columns(\"*\").buildURL()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := \"/_cat/snapshots/my_repo\", urls; want != have {\n\t\tt.Fatalf(\"want URL=%q, have %q\", want, have)\n\t}\n\tif want, have := \"format=json&h=%2A\", params.Encode(); want != have {\n\t\tt.Fatalf(\"want Params=%q, have %q\", want, have)\n\t}\n}\n"
  },
  {
    "path": "clear_scroll.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// ClearScrollService clears one or more scroll contexts by their ids.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-scroll.html#_clear_scroll_api\n// for details.\ntype ClearScrollService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tscrollId []string\n}\n\n// NewClearScrollService creates a new ClearScrollService.\nfunc NewClearScrollService(client *Client) *ClearScrollService {\n\treturn &ClearScrollService{\n\t\tclient:   client,\n\t\tscrollId: make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ClearScrollService) Pretty(pretty bool) *ClearScrollService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ClearScrollService) Human(human bool) *ClearScrollService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ClearScrollService) ErrorTrace(errorTrace bool) *ClearScrollService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ClearScrollService) FilterPath(filterPath ...string) *ClearScrollService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ClearScrollService) Header(name string, value string) *ClearScrollService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ClearScrollService) Headers(headers http.Header) *ClearScrollService {\n\ts.headers = headers\n\treturn s\n}\n\n// ScrollId is a list of scroll IDs to clear.\n// Use _all to clear all search contexts.\nfunc (s *ClearScrollService) ScrollId(scrollIds ...string) *ClearScrollService {\n\ts.scrollId = append(s.scrollId, scrollIds...)\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ClearScrollService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath := \"/_search/scroll/\"\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ClearScrollService) Validate() error {\n\tvar invalid []string\n\tif len(s.scrollId) == 0 {\n\t\tinvalid = append(invalid, \"ScrollId\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *ClearScrollService) Do(ctx context.Context) (*ClearScrollResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tbody := map[string][]string{\n\t\t\"scroll_id\": s.scrollId,\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(ClearScrollResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// ClearScrollResponse is the response of ClearScrollService.Do.\ntype ClearScrollResponse struct {\n\tSucceeded bool `json:\"succeeded,omitempty\"`\n\tNumFreed  int  `json:\"num_freed,omitempty\"`\n}\n"
  },
  {
    "path": "clear_scroll_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t_ \"net/http\"\n\t\"testing\"\n)\n\nfunc TestClearScroll(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\tres, err := client.Scroll(testIndexName).Size(1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected results != nil; got nil\")\n\t}\n\tif res.ScrollId == \"\" {\n\t\tt.Fatalf(\"expected scrollId in results; got %q\", res.ScrollId)\n\t}\n\n\t// Search should succeed\n\t_, err = client.Scroll(testIndexName).Size(1).ScrollId(res.ScrollId).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Clear scroll id\n\tclearScrollRes, err := client.ClearScroll().ScrollId(res.ScrollId).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif clearScrollRes == nil {\n\t\tt.Fatal(\"expected results != nil; got nil\")\n\t}\n\n\t// Search result should fail\n\t_, err = client.Scroll(testIndexName).Size(1).ScrollId(res.ScrollId).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected scroll to fail\")\n\t}\n}\n\nfunc TestClearScrollValidate(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// No scroll id -> fail with error\n\tres, err := NewClearScrollService(client).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected ClearScroll to fail without scroll ids\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected result to be nil; got: %v\", res)\n\t}\n}\n"
  },
  {
    "path": "client.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"net/http/httputil\"\n\t\"net/url\"\n\t\"os\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/olivere/elastic/v7/config\"\n)\n\nconst (\n\t// Version is the current version of Elastic.\n\tVersion = \"7.0.32\"\n\n\t// DefaultURL is the default endpoint of Elasticsearch on the local machine.\n\t// It is used e.g. when initializing a new Client without a specific URL.\n\tDefaultURL = \"http://127.0.0.1:9200\"\n\n\t// DefaultScheme is the default protocol scheme to use when sniffing\n\t// the Elasticsearch cluster.\n\tDefaultScheme = \"http\"\n\n\t// DefaultHealthcheckEnabled specifies if healthchecks are enabled by default.\n\tDefaultHealthcheckEnabled = true\n\n\t// DefaultHealthcheckTimeoutStartup is the time the healthcheck waits\n\t// for a response from Elasticsearch on startup, i.e. when creating a\n\t// client. After the client is started, a shorter timeout is commonly used\n\t// (its default is specified in DefaultHealthcheckTimeout).\n\tDefaultHealthcheckTimeoutStartup = 5 * time.Second\n\n\t// DefaultHealthcheckTimeout specifies the time a running client waits for\n\t// a response from Elasticsearch. Notice that the healthcheck timeout\n\t// when a client is created is larger by default (see DefaultHealthcheckTimeoutStartup).\n\tDefaultHealthcheckTimeout = 1 * time.Second\n\n\t// DefaultHealthcheckInterval is the default interval between\n\t// two health checks of the nodes in the cluster.\n\tDefaultHealthcheckInterval = 60 * time.Second\n\n\t// DefaultSnifferEnabled specifies if the sniffer is enabled by default.\n\tDefaultSnifferEnabled = true\n\n\t// DefaultSnifferInterval is the interval between two sniffing procedures,\n\t// i.e. the lookup of all nodes in the cluster and their addition/removal\n\t// from the list of actual connections.\n\tDefaultSnifferInterval = 15 * time.Minute\n\n\t// DefaultSnifferTimeoutStartup is the default timeout for the sniffing\n\t// process that is initiated while creating a new client. For subsequent\n\t// sniffing processes, DefaultSnifferTimeout is used (by default).\n\tDefaultSnifferTimeoutStartup = 5 * time.Second\n\n\t// DefaultSnifferTimeout is the default timeout after which the\n\t// sniffing process times out. Notice that for the initial sniffing\n\t// process, DefaultSnifferTimeoutStartup is used.\n\tDefaultSnifferTimeout = 2 * time.Second\n\n\t// DefaultSendGetBodyAs is the HTTP method to use when elastic is sending\n\t// a GET request with a body.\n\tDefaultSendGetBodyAs = \"GET\"\n\n\t// DefaultGzipEnabled specifies if gzip compression is enabled by default.\n\tDefaultGzipEnabled = false\n\n\t// off is used to disable timeouts.\n\toff = -1 * time.Second\n)\n\nvar (\n\t// nilByte is used in JSON marshal/unmarshal\n\tnilByte = []byte(\"null\")\n\n\t// ErrNoClient is raised when no Elasticsearch node is available.\n\tErrNoClient = errors.New(\"no Elasticsearch node available\")\n\n\t// ErrRetry is raised when a request cannot be executed after the configured\n\t// number of retries.\n\tErrRetry = errors.New(\"cannot connect after several retries\")\n\n\t// ErrTimeout is raised when a request timed out, e.g. when WaitForStatus\n\t// didn't return in time.\n\tErrTimeout = errors.New(\"timeout\")\n\n\t// noRetries is a retrier that does not retry.\n\tnoRetries = NewStopRetrier()\n\n\t// noDeprecationLog is a no-op for logging deprecations.\n\tnoDeprecationLog = func(*http.Request, *http.Response) {}\n)\n\n// Doer is an interface to perform HTTP requests.\n// It can be used for mocking.\ntype Doer interface {\n\tDo(*http.Request) (*http.Response, error)\n}\n\n// ClientOptionFunc is a function that configures a Client.\n// It is used in NewClient.\ntype ClientOptionFunc func(*Client) error\n\n// Client is an Elasticsearch client. Create one by calling NewClient.\ntype Client struct {\n\tc Doer // e.g. a net/*http.Client to use for requests\n\n\tconnsMu sync.RWMutex // connsMu guards the next block\n\tconns   []*conn      // all connections\n\tcindex  int          // index into conns\n\n\tmu                        sync.RWMutex // guards the next block\n\turls                      []string     // set of URLs passed initially to the client\n\trunning                   bool         // true if the client's background processes are running\n\terrorlog                  Logger       // error log for critical messages\n\tinfolog                   Logger       // information log for e.g. response times\n\ttracelog                  Logger       // trace log for debugging\n\tdeprecationlog            func(*http.Request, *http.Response)\n\tscheme                    string          // http or https\n\thealthcheckEnabled        bool            // healthchecks enabled or disabled\n\thealthcheckTimeoutStartup time.Duration   // time the healthcheck waits for a response from Elasticsearch on startup\n\thealthcheckTimeout        time.Duration   // time the healthcheck waits for a response from Elasticsearch\n\thealthcheckInterval       time.Duration   // interval between healthchecks\n\thealthcheckStop           chan bool       // notify healthchecker to stop, and notify back\n\tsnifferEnabled            bool            // sniffer enabled or disabled\n\tsnifferTimeoutStartup     time.Duration   // time the sniffer waits for a response from nodes info API on startup\n\tsnifferTimeout            time.Duration   // time the sniffer waits for a response from nodes info API\n\tsnifferInterval           time.Duration   // interval between sniffing\n\tsnifferCallback           SnifferCallback // callback to modify the sniffing decision\n\tsnifferStop               chan bool       // notify sniffer to stop, and notify back\n\tdecoder                   Decoder         // used to decode data sent from Elasticsearch\n\tbasicAuthUsername         string          // username for HTTP Basic Auth\n\tbasicAuthPassword         string          // password for HTTP Basic Auth\n\tsendGetBodyAs             string          // override for when sending a GET with a body\n\tgzipEnabled               bool            // gzip compression enabled or disabled (default)\n\trequiredPlugins           []string        // list of required plugins\n\tretrier                   Retrier         // strategy for retries\n\tretryStatusCodes          []int           // HTTP status codes where to retry automatically (with retrier)\n\theaders                   http.Header     // a list of default headers to add to each request\n}\n\n// NewClient creates a new client to work with Elasticsearch.\n//\n// NewClient, by default, is meant to be long-lived and shared across\n// your application. If you need a short-lived client, e.g. for request-scope,\n// consider using NewSimpleClient instead.\n//\n// The caller can configure the new client by passing configuration options\n// to the func.\n//\n// Example:\n//\n//   client, err := elastic.NewClient(\n//     elastic.SetURL(\"http://127.0.0.1:9200\", \"http://127.0.0.1:9201\"),\n//     elastic.SetBasicAuth(\"user\", \"secret\"))\n//\n// If no URL is configured, Elastic uses DefaultURL by default.\n//\n// If the sniffer is enabled (the default), the new client then sniffes\n// the cluster via the Nodes Info API\n// (see https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cluster-nodes-info.html#cluster-nodes-info).\n// It uses the URLs specified by the caller. The caller is responsible\n// to only pass a list of URLs of nodes that belong to the same cluster.\n// This sniffing process is run on startup and periodically.\n// Use SnifferInterval to set the interval between two sniffs (default is\n// 15 minutes). In other words: By default, the client will find new nodes\n// in the cluster and remove those that are no longer available every\n// 15 minutes. Disable the sniffer by passing SetSniff(false) to NewClient.\n//\n// The list of nodes found in the sniffing process will be used to make\n// connections to the REST API of Elasticsearch. These nodes are also\n// periodically checked in a shorter time frame. This process is called\n// a health check. By default, a health check is done every 60 seconds.\n// You can set a shorter or longer interval by SetHealthcheckInterval.\n// Disabling health checks is not recommended, but can be done by\n// SetHealthcheck(false).\n//\n// Connections are automatically marked as dead or healthy while\n// making requests to Elasticsearch. When a request fails, Elastic will\n// call into the Retry strategy which can be specified with SetRetry.\n// The Retry strategy is also responsible for handling backoff i.e. the time\n// to wait before starting the next request. There are various standard\n// backoff implementations, e.g. ExponentialBackoff or SimpleBackoff.\n// Retries are disabled by default.\n//\n// If no HttpClient is configured, then http.DefaultClient is used.\n// You can use your own http.Client with some http.Transport for\n// advanced scenarios.\n//\n// An error is also returned when some configuration option is invalid or\n// the new client cannot sniff the cluster (if enabled).\nfunc NewClient(options ...ClientOptionFunc) (*Client, error) {\n\treturn DialContext(context.Background(), options...)\n}\n\n// NewClientFromConfig initializes a client from a configuration.\nfunc NewClientFromConfig(cfg *config.Config) (*Client, error) {\n\toptions, err := configToOptions(cfg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn DialContext(context.Background(), options...)\n}\n\n// NewSimpleClient creates a new short-lived Client that can be used in\n// use cases where you need e.g. one client per request.\n//\n// While NewClient by default sets up e.g. periodic health checks\n// and sniffing for new nodes in separate goroutines, NewSimpleClient does\n// not and is meant as a simple replacement where you don't need all the\n// heavy lifting of NewClient.\n//\n// NewSimpleClient does the following by default: First, all health checks\n// are disabled, including timeouts and periodic checks. Second, sniffing\n// is disabled, including timeouts and periodic checks. The number of retries\n// is set to 1. NewSimpleClient also does not start any goroutines.\n//\n// Notice that you can still override settings by passing additional options,\n// just like with NewClient.\nfunc NewSimpleClient(options ...ClientOptionFunc) (*Client, error) {\n\tc := &Client{\n\t\tc:                         http.DefaultClient,\n\t\tconns:                     make([]*conn, 0),\n\t\tcindex:                    -1,\n\t\tscheme:                    DefaultScheme,\n\t\tdecoder:                   &DefaultDecoder{},\n\t\thealthcheckEnabled:        false,\n\t\thealthcheckTimeoutStartup: off,\n\t\thealthcheckTimeout:        off,\n\t\thealthcheckInterval:       off,\n\t\thealthcheckStop:           make(chan bool),\n\t\tsnifferEnabled:            false,\n\t\tsnifferTimeoutStartup:     off,\n\t\tsnifferTimeout:            off,\n\t\tsnifferInterval:           off,\n\t\tsnifferCallback:           nopSnifferCallback,\n\t\tsnifferStop:               make(chan bool),\n\t\tsendGetBodyAs:             DefaultSendGetBodyAs,\n\t\tgzipEnabled:               DefaultGzipEnabled,\n\t\tretrier:                   noRetries, // no retries by default\n\t\tretryStatusCodes:          nil,       // no automatic retries for specific HTTP status codes\n\t\tdeprecationlog:            noDeprecationLog,\n\t}\n\n\t// Run the options on it\n\tfor _, option := range options {\n\t\tif err := option(c); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// Use a default URL and normalize them\n\tif len(c.urls) == 0 {\n\t\tc.urls = []string{DefaultURL}\n\t}\n\tc.urls = canonicalize(c.urls...)\n\n\t// If the URLs have auth info, use them here as an alternative to SetBasicAuth\n\tif c.basicAuthUsername == \"\" && c.basicAuthPassword == \"\" {\n\t\tfor _, urlStr := range c.urls {\n\t\t\tu, err := url.Parse(urlStr)\n\t\t\tif err == nil && u.User != nil {\n\t\t\t\tc.basicAuthUsername = u.User.Username()\n\t\t\t\tc.basicAuthPassword, _ = u.User.Password()\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tfor _, url := range c.urls {\n\t\tc.conns = append(c.conns, newConn(url, url))\n\t}\n\n\t// Ensure that we have at least one connection available\n\tif err := c.mustActiveConn(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Check the required plugins\n\tfor _, plugin := range c.requiredPlugins {\n\t\tfound, err := c.HasPlugin(plugin)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif !found {\n\t\t\treturn nil, fmt.Errorf(\"elastic: plugin %s not found\", plugin)\n\t\t}\n\t}\n\n\tc.mu.Lock()\n\tc.running = true\n\tc.mu.Unlock()\n\n\treturn c, nil\n}\n\n// Dial will call DialContext with a background context.\nfunc Dial(options ...ClientOptionFunc) (*Client, error) {\n\treturn DialContext(context.Background(), options...)\n}\n\n// DialContext will connect to Elasticsearch, just like NewClient does.\n//\n// The context is honoured in terms of e.g. cancellation.\nfunc DialContext(ctx context.Context, options ...ClientOptionFunc) (*Client, error) {\n\t// Set up the client\n\tc := &Client{\n\t\tc:                         http.DefaultClient,\n\t\tconns:                     make([]*conn, 0),\n\t\tcindex:                    -1,\n\t\tscheme:                    DefaultScheme,\n\t\tdecoder:                   &DefaultDecoder{},\n\t\thealthcheckEnabled:        DefaultHealthcheckEnabled,\n\t\thealthcheckTimeoutStartup: DefaultHealthcheckTimeoutStartup,\n\t\thealthcheckTimeout:        DefaultHealthcheckTimeout,\n\t\thealthcheckInterval:       DefaultHealthcheckInterval,\n\t\thealthcheckStop:           make(chan bool),\n\t\tsnifferEnabled:            DefaultSnifferEnabled,\n\t\tsnifferTimeoutStartup:     DefaultSnifferTimeoutStartup,\n\t\tsnifferTimeout:            DefaultSnifferTimeout,\n\t\tsnifferInterval:           DefaultSnifferInterval,\n\t\tsnifferCallback:           nopSnifferCallback,\n\t\tsnifferStop:               make(chan bool),\n\t\tsendGetBodyAs:             DefaultSendGetBodyAs,\n\t\tgzipEnabled:               DefaultGzipEnabled,\n\t\tretrier:                   noRetries, // no retries by default\n\t\tretryStatusCodes:          nil,       // no automatic retries for specific HTTP status codes\n\t\tdeprecationlog:            noDeprecationLog,\n\t}\n\n\t// Run the options on it\n\tfor _, option := range options {\n\t\tif err := option(c); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// Use a default URL and normalize them\n\tif len(c.urls) == 0 {\n\t\tc.urls = []string{DefaultURL}\n\t}\n\tc.urls = canonicalize(c.urls...)\n\n\t// If the URLs have auth info, use them here as an alternative to SetBasicAuth\n\tif c.basicAuthUsername == \"\" && c.basicAuthPassword == \"\" {\n\t\tfor _, urlStr := range c.urls {\n\t\t\tu, err := url.Parse(urlStr)\n\t\t\tif err == nil && u.User != nil {\n\t\t\t\tc.basicAuthUsername = u.User.Username()\n\t\t\t\tc.basicAuthPassword, _ = u.User.Password()\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check if we can make a request to any of the specified URLs\n\tif c.healthcheckEnabled {\n\t\tif err := c.startupHealthcheck(ctx, c.healthcheckTimeoutStartup); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif c.snifferEnabled {\n\t\t// Sniff the cluster initially\n\t\tif err := c.sniff(ctx, c.snifferTimeoutStartup); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t} else {\n\t\t// Do not sniff the cluster initially. Use the provided URLs instead.\n\t\tfor _, url := range c.urls {\n\t\t\tc.conns = append(c.conns, newConn(url, url))\n\t\t}\n\t}\n\n\tif c.healthcheckEnabled {\n\t\t// Perform an initial health check\n\t\tc.healthcheck(ctx, c.healthcheckTimeoutStartup, true)\n\t}\n\t// Ensure that we have at least one connection available\n\tif err := c.mustActiveConn(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Check the required plugins\n\tfor _, plugin := range c.requiredPlugins {\n\t\tfound, err := c.HasPlugin(plugin)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif !found {\n\t\t\treturn nil, fmt.Errorf(\"elastic: plugin %s not found\", plugin)\n\t\t}\n\t}\n\n\tif c.snifferEnabled {\n\t\tgo c.sniffer() // periodically update cluster information\n\t}\n\tif c.healthcheckEnabled {\n\t\tgo c.healthchecker() // start goroutine periodically ping all nodes of the cluster\n\t}\n\n\tc.mu.Lock()\n\tc.running = true\n\tc.mu.Unlock()\n\n\treturn c, nil\n}\n\n// DialWithConfig will use the configuration settings parsed from config package\n// to connect to Elasticsearch.\n//\n// The context is honoured in terms of e.g. cancellation.\nfunc DialWithConfig(ctx context.Context, cfg *config.Config) (*Client, error) {\n\toptions, err := configToOptions(cfg)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn DialContext(ctx, options...)\n}\n\nfunc configToOptions(cfg *config.Config) ([]ClientOptionFunc, error) {\n\tvar options []ClientOptionFunc\n\tif cfg != nil {\n\t\tif cfg.URL != \"\" {\n\t\t\toptions = append(options, SetURL(cfg.URL))\n\t\t}\n\t\tif cfg.Errorlog != \"\" {\n\t\t\tf, err := os.OpenFile(cfg.Errorlog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"unable to initialize error log\")\n\t\t\t}\n\t\t\tl := log.New(f, \"\", 0)\n\t\t\toptions = append(options, SetErrorLog(l))\n\t\t}\n\t\tif cfg.Tracelog != \"\" {\n\t\t\tf, err := os.OpenFile(cfg.Tracelog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"unable to initialize trace log\")\n\t\t\t}\n\t\t\tl := log.New(f, \"\", 0)\n\t\t\toptions = append(options, SetTraceLog(l))\n\t\t}\n\t\tif cfg.Infolog != \"\" {\n\t\t\tf, err := os.OpenFile(cfg.Infolog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrap(err, \"unable to initialize info log\")\n\t\t\t}\n\t\t\tl := log.New(f, \"\", 0)\n\t\t\toptions = append(options, SetInfoLog(l))\n\t\t}\n\t\tif cfg.Username != \"\" || cfg.Password != \"\" {\n\t\t\toptions = append(options, SetBasicAuth(cfg.Username, cfg.Password))\n\t\t}\n\t\tif cfg.Sniff != nil {\n\t\t\toptions = append(options, SetSniff(*cfg.Sniff))\n\t\t}\n\t\tif cfg.Healthcheck != nil {\n\t\t\toptions = append(options, SetHealthcheck(*cfg.Healthcheck))\n\t\t}\n\t}\n\treturn options, nil\n}\n\n// SetHttpClient can be used to specify the http.Client to use when making\n// HTTP requests to Elasticsearch.\nfunc SetHttpClient(httpClient Doer) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tif httpClient != nil {\n\t\t\tc.c = httpClient\n\t\t} else {\n\t\t\tc.c = http.DefaultClient\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// SetBasicAuth can be used to specify the HTTP Basic Auth credentials to\n// use when making HTTP requests to Elasticsearch.\nfunc SetBasicAuth(username, password string) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.basicAuthUsername = username\n\t\tc.basicAuthPassword = password\n\t\treturn nil\n\t}\n}\n\n// SetURL defines the URL endpoints of the Elasticsearch nodes. Notice that\n// when sniffing is enabled, these URLs are used to initially sniff the\n// cluster on startup.\nfunc SetURL(urls ...string) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tswitch len(urls) {\n\t\tcase 0:\n\t\t\tc.urls = []string{DefaultURL}\n\t\tdefault:\n\t\t\tc.urls = urls\n\t\t}\n\t\t// Check URLs\n\t\tfor _, urlStr := range c.urls {\n\t\t\tif _, err := url.Parse(urlStr); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// SetScheme sets the HTTP scheme to look for when sniffing (http or https).\n// This is http by default.\nfunc SetScheme(scheme string) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.scheme = scheme\n\t\treturn nil\n\t}\n}\n\n// SetSniff enables or disables the sniffer (enabled by default).\nfunc SetSniff(enabled bool) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.snifferEnabled = enabled\n\t\treturn nil\n\t}\n}\n\n// SetSnifferTimeoutStartup sets the timeout for the sniffer that is used\n// when creating a new client. The default is 5 seconds. Notice that the\n// timeout being used for subsequent sniffing processes is set with\n// SetSnifferTimeout.\nfunc SetSnifferTimeoutStartup(timeout time.Duration) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.snifferTimeoutStartup = timeout\n\t\treturn nil\n\t}\n}\n\n// SetSnifferTimeout sets the timeout for the sniffer that finds the\n// nodes in a cluster. The default is 2 seconds. Notice that the timeout\n// used when creating a new client on startup is usually greater and can\n// be set with SetSnifferTimeoutStartup.\nfunc SetSnifferTimeout(timeout time.Duration) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.snifferTimeout = timeout\n\t\treturn nil\n\t}\n}\n\n// SetSnifferInterval sets the interval between two sniffing processes.\n// The default interval is 15 minutes.\nfunc SetSnifferInterval(interval time.Duration) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.snifferInterval = interval\n\t\treturn nil\n\t}\n}\n\n// SnifferCallback defines the protocol for sniffing decisions.\ntype SnifferCallback func(*NodesInfoNode) bool\n\n// nopSnifferCallback is the default sniffer callback: It accepts\n// all nodes the sniffer finds.\nvar nopSnifferCallback = func(*NodesInfoNode) bool { return true }\n\n// SetSnifferCallback allows the caller to modify sniffer decisions.\n// When setting the callback, the given SnifferCallback is called for\n// each (healthy) node found during the sniffing process.\n// If the callback returns false, the node is ignored: No requests\n// are routed to it.\nfunc SetSnifferCallback(f SnifferCallback) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tif f != nil {\n\t\t\tc.snifferCallback = f\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// SetHealthcheck enables or disables healthchecks (enabled by default).\nfunc SetHealthcheck(enabled bool) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.healthcheckEnabled = enabled\n\t\treturn nil\n\t}\n}\n\n// SetHealthcheckTimeoutStartup sets the timeout for the initial health check.\n// The default timeout is 5 seconds (see DefaultHealthcheckTimeoutStartup).\n// Notice that timeouts for subsequent health checks can be modified with\n// SetHealthcheckTimeout.\nfunc SetHealthcheckTimeoutStartup(timeout time.Duration) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.healthcheckTimeoutStartup = timeout\n\t\treturn nil\n\t}\n}\n\n// SetHealthcheckTimeout sets the timeout for periodic health checks.\n// The default timeout is 1 second (see DefaultHealthcheckTimeout).\n// Notice that a different (usually larger) timeout is used for the initial\n// healthcheck, which is initiated while creating a new client.\n// The startup timeout can be modified with SetHealthcheckTimeoutStartup.\nfunc SetHealthcheckTimeout(timeout time.Duration) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.healthcheckTimeout = timeout\n\t\treturn nil\n\t}\n}\n\n// SetHealthcheckInterval sets the interval between two health checks.\n// The default interval is 60 seconds.\nfunc SetHealthcheckInterval(interval time.Duration) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.healthcheckInterval = interval\n\t\treturn nil\n\t}\n}\n\n// SetMaxRetries sets the maximum number of retries before giving up when\n// performing a HTTP request to Elasticsearch.\n//\n// Deprecated: Replace with a Retry implementation.\nfunc SetMaxRetries(maxRetries int) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tif maxRetries < 0 {\n\t\t\treturn errors.New(\"MaxRetries must be greater than or equal to 0\")\n\t\t} else if maxRetries == 0 {\n\t\t\tc.retrier = noRetries\n\t\t} else {\n\t\t\t// Create a Retrier that will wait for 100ms (+/- jitter) between requests.\n\t\t\t// This resembles the old behavior with maxRetries.\n\t\t\tticks := make([]int, maxRetries)\n\t\t\tfor i := 0; i < len(ticks); i++ {\n\t\t\t\tticks[i] = 100\n\t\t\t}\n\t\t\tbackoff := NewSimpleBackoff(ticks...)\n\t\t\tc.retrier = NewBackoffRetrier(backoff)\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// SetGzip enables or disables gzip compression (disabled by default).\nfunc SetGzip(enabled bool) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.gzipEnabled = enabled\n\t\treturn nil\n\t}\n}\n\n// SetDecoder sets the Decoder to use when decoding data from Elasticsearch.\n// DefaultDecoder is used by default.\nfunc SetDecoder(decoder Decoder) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tif decoder != nil {\n\t\t\tc.decoder = decoder\n\t\t} else {\n\t\t\tc.decoder = &DefaultDecoder{}\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// SetRequiredPlugins can be used to indicate that some plugins are required\n// before a Client will be created.\nfunc SetRequiredPlugins(plugins ...string) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tif c.requiredPlugins == nil {\n\t\t\tc.requiredPlugins = make([]string, 0)\n\t\t}\n\t\tc.requiredPlugins = append(c.requiredPlugins, plugins...)\n\t\treturn nil\n\t}\n}\n\n// SetErrorLog sets the logger for critical messages like nodes joining\n// or leaving the cluster or failing requests. It is nil by default.\nfunc SetErrorLog(logger Logger) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.errorlog = logger\n\t\treturn nil\n\t}\n}\n\n// SetInfoLog sets the logger for informational messages, e.g. requests\n// and their response times. It is nil by default.\nfunc SetInfoLog(logger Logger) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.infolog = logger\n\t\treturn nil\n\t}\n}\n\n// SetTraceLog specifies the log.Logger to use for output of HTTP requests\n// and responses which is helpful during debugging. It is nil by default.\nfunc SetTraceLog(logger Logger) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.tracelog = logger\n\t\treturn nil\n\t}\n}\n\n// SetSendGetBodyAs specifies the HTTP method to use when sending a GET request\n// with a body. It is GET by default.\nfunc SetSendGetBodyAs(httpMethod string) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.sendGetBodyAs = httpMethod\n\t\treturn nil\n\t}\n}\n\n// SetRetrier specifies the retry strategy that handles errors during\n// HTTP request/response with Elasticsearch.\nfunc SetRetrier(retrier Retrier) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tif retrier == nil {\n\t\t\tretrier = noRetries // no retries by default\n\t\t}\n\t\tc.retrier = retrier\n\t\treturn nil\n\t}\n}\n\n// SetRetryStatusCodes specifies the HTTP status codes where the client\n// will retry automatically. Notice that retries call the specified retrier,\n// so calling SetRetryStatusCodes without setting a Retrier won't do anything\n// for retries.\nfunc SetRetryStatusCodes(statusCodes ...int) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.retryStatusCodes = statusCodes\n\t\treturn nil\n\t}\n}\n\n// SetHeaders adds a list of default HTTP headers that will be added to\n// each requests executed by PerformRequest.\nfunc SetHeaders(headers http.Header) ClientOptionFunc {\n\treturn func(c *Client) error {\n\t\tc.headers = headers\n\t\treturn nil\n\t}\n}\n\n// String returns a string representation of the client status.\nfunc (c *Client) String() string {\n\tc.connsMu.Lock()\n\tconns := c.conns\n\tc.connsMu.Unlock()\n\n\tvar buf bytes.Buffer\n\tfor i, conn := range conns {\n\t\tif i > 0 {\n\t\t\tbuf.WriteString(\", \")\n\t\t}\n\t\tbuf.WriteString(conn.String())\n\t}\n\treturn buf.String()\n}\n\n// IsRunning returns true if the background processes of the client are\n// running, false otherwise.\nfunc (c *Client) IsRunning() bool {\n\tc.mu.RLock()\n\tdefer c.mu.RUnlock()\n\treturn c.running\n}\n\n// Start starts the background processes like sniffing the cluster and\n// periodic health checks. You don't need to run Start when creating a\n// client with NewClient; the background processes are run by default.\n//\n// If the background processes are already running, this is a no-op.\nfunc (c *Client) Start() {\n\tc.mu.RLock()\n\tif c.running {\n\t\tc.mu.RUnlock()\n\t\treturn\n\t}\n\tc.mu.RUnlock()\n\n\tif c.snifferEnabled {\n\t\tgo c.sniffer()\n\t}\n\tif c.healthcheckEnabled {\n\t\tgo c.healthchecker()\n\t}\n\n\tc.mu.Lock()\n\tc.running = true\n\tc.mu.Unlock()\n\n\tc.infof(\"elastic: client started\")\n}\n\n// Stop stops the background processes that the client is running,\n// i.e. sniffing the cluster periodically and running health checks\n// on the nodes.\n//\n// If the background processes are not running, this is a no-op.\nfunc (c *Client) Stop() {\n\tc.mu.RLock()\n\tif !c.running {\n\t\tc.mu.RUnlock()\n\t\treturn\n\t}\n\tc.mu.RUnlock()\n\n\tif c.healthcheckEnabled {\n\t\tc.healthcheckStop <- true\n\t\t<-c.healthcheckStop\n\t}\n\n\tif c.snifferEnabled {\n\t\tc.snifferStop <- true\n\t\t<-c.snifferStop\n\t}\n\n\tc.mu.Lock()\n\tc.running = false\n\tc.mu.Unlock()\n\n\tc.infof(\"elastic: client stopped\")\n}\n\n// errorf logs to the error log.\nfunc (c *Client) errorf(format string, args ...interface{}) {\n\tif c.errorlog != nil {\n\t\tc.errorlog.Printf(format, args...)\n\t}\n}\n\n// infof logs informational messages.\nfunc (c *Client) infof(format string, args ...interface{}) {\n\tif c.infolog != nil {\n\t\tc.infolog.Printf(format, args...)\n\t}\n}\n\n// tracef logs to the trace log.\nfunc (c *Client) tracef(format string, args ...interface{}) {\n\tif c.tracelog != nil {\n\t\tc.tracelog.Printf(format, args...)\n\t}\n}\n\n// dumpRequest dumps the given HTTP request to the trace log.\nfunc (c *Client) dumpRequest(r *http.Request) {\n\tif c.tracelog != nil {\n\t\tout, err := httputil.DumpRequestOut(r, true)\n\t\tif err == nil {\n\t\t\tc.tracef(\"%s\\n\", string(out))\n\t\t}\n\t}\n}\n\n// dumpResponse dumps the given HTTP response to the trace log.\nfunc (c *Client) dumpResponse(resp *http.Response) {\n\tif c.tracelog != nil {\n\t\tout, err := httputil.DumpResponse(resp, true)\n\t\tif err == nil {\n\t\t\tc.tracef(\"%s\\n\", string(out))\n\t\t}\n\t}\n}\n\n// sniffer periodically runs sniff.\nfunc (c *Client) sniffer() {\n\tc.mu.RLock()\n\ttimeout := c.snifferTimeout\n\tinterval := c.snifferInterval\n\tc.mu.RUnlock()\n\n\tticker := time.NewTicker(interval)\n\tdefer ticker.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase <-c.snifferStop:\n\t\t\t// we are asked to stop, so we signal back that we're stopping now\n\t\t\tc.snifferStop <- true\n\t\t\treturn\n\t\tcase <-ticker.C:\n\t\t\tc.sniff(context.Background(), timeout)\n\t\t}\n\t}\n}\n\n// sniff uses the Node Info API to return the list of nodes in the cluster.\n// It uses the list of URLs passed on startup plus the list of URLs found\n// by the preceding sniffing process (if sniffing is enabled).\n//\n// If sniffing is disabled, this is a no-op.\nfunc (c *Client) sniff(parentCtx context.Context, timeout time.Duration) error {\n\tc.mu.RLock()\n\tif !c.snifferEnabled {\n\t\tc.mu.RUnlock()\n\t\treturn nil\n\t}\n\n\t// Use all available URLs provided to sniff the cluster.\n\tvar urls []string\n\turlsMap := make(map[string]bool)\n\n\t// Add all URLs provided on startup\n\tfor _, url := range c.urls {\n\t\turlsMap[url] = true\n\t\turls = append(urls, url)\n\t}\n\tc.mu.RUnlock()\n\n\t// Add all URLs found by sniffing\n\tc.connsMu.RLock()\n\tfor _, conn := range c.conns {\n\t\tif !conn.IsDead() {\n\t\t\turl := conn.URL()\n\t\t\tif _, found := urlsMap[url]; !found {\n\t\t\t\turls = append(urls, url)\n\t\t\t}\n\t\t}\n\t}\n\tc.connsMu.RUnlock()\n\n\tif len(urls) == 0 {\n\t\treturn errors.Wrap(ErrNoClient, \"no URLs found\")\n\t}\n\n\t// Start sniffing on all found URLs\n\tch := make(chan []*conn, len(urls))\n\n\tctx, cancel := context.WithTimeout(parentCtx, timeout)\n\tdefer cancel()\n\n\tfor _, url := range urls {\n\t\tgo func(url string) { ch <- c.sniffNode(ctx, url) }(url)\n\t}\n\n\t// Wait for the results to come back, or the process times out.\n\tfor {\n\t\tselect {\n\t\tcase conns := <-ch:\n\t\t\tif len(conns) > 0 {\n\t\t\t\tc.updateConns(conns)\n\t\t\t\treturn nil\n\t\t\t}\n\t\tcase <-ctx.Done():\n\t\t\tif err := ctx.Err(); err != nil {\n\t\t\t\tswitch {\n\t\t\t\tcase IsContextErr(err):\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\treturn errors.Wrapf(ErrNoClient, \"sniff timeout: %v\", err)\n\t\t\t}\n\t\t\t// We get here if no cluster responds in time\n\t\t\treturn errors.Wrap(ErrNoClient, \"sniff timeout\")\n\t\t}\n\t}\n}\n\n// sniffNode sniffs a single node. This method is run as a goroutine\n// in sniff. If successful, it returns the list of node URLs extracted\n// from the result of calling Nodes Info API. Otherwise, an empty array\n// is returned.\nfunc (c *Client) sniffNode(ctx context.Context, url string) []*conn {\n\tvar nodes []*conn\n\n\t// Call the Nodes Info API at /_nodes/http\n\treq, err := NewRequest(\"GET\", url+\"/_nodes/http\")\n\tif err != nil {\n\t\treturn nodes\n\t}\n\n\tc.mu.RLock()\n\tif c.basicAuthUsername != \"\" || c.basicAuthPassword != \"\" {\n\t\treq.SetBasicAuth(c.basicAuthUsername, c.basicAuthPassword)\n\t}\n\tc.mu.RUnlock()\n\n\tif req.Header.Get(\"User-Agent\") == \"\" {\n\t\treq.Header.Add(\"User-Agent\", \"elastic/\"+Version+\" (\"+runtime.GOOS+\"-\"+runtime.GOARCH+\")\")\n\t}\n\n\tres, err := c.c.Do((*http.Request)(req).WithContext(ctx))\n\tif err != nil {\n\t\treturn nodes\n\t}\n\tdefer res.Body.Close()\n\n\tvar info NodesInfoResponse\n\tif err := json.NewDecoder(res.Body).Decode(&info); err == nil {\n\t\tif len(info.Nodes) > 0 {\n\t\t\tfor nodeID, node := range info.Nodes {\n\t\t\t\tif c.snifferCallback(node) {\n\t\t\t\t\tif node.HTTP != nil && len(node.HTTP.PublishAddress) > 0 {\n\t\t\t\t\t\turl := c.extractHostname(c.scheme, node.HTTP.PublishAddress)\n\t\t\t\t\t\tif url != \"\" {\n\t\t\t\t\t\t\tnodes = append(nodes, newConn(nodeID, url))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nodes\n}\n\n// extractHostname returns the URL from the http.publish_address setting.\nfunc (c *Client) extractHostname(scheme, address string) string {\n\tvar (\n\t\thost string\n\t\tport string\n\n\t\taddrs = strings.Split(address, \"/\")\n\t\tports = strings.Split(address, \":\")\n\t)\n\n\tif len(addrs) > 1 {\n\t\thost = addrs[0]\n\t} else {\n\t\thost = strings.Split(addrs[0], \":\")[0]\n\t}\n\tport = ports[len(ports)-1]\n\n\treturn fmt.Sprintf(\"%s://%s:%s\", scheme, host, port)\n}\n\n// updateConns updates the clients' connections with new information\n// gather by a sniff operation.\nfunc (c *Client) updateConns(conns []*conn) {\n\tc.connsMu.Lock()\n\n\t// Build up new connections:\n\t// If we find an existing connection, use that (including no. of failures etc.).\n\t// If we find a new connection, add it.\n\tvar newConns []*conn\n\tfor _, conn := range conns {\n\t\tvar found bool\n\t\tfor _, oldConn := range c.conns {\n\t\t\t// Notice that e.g. in a Kubernetes cluster the NodeID might be\n\t\t\t// stable while the URL has changed.\n\t\t\tif oldConn.NodeID() == conn.NodeID() && oldConn.URL() == conn.URL() {\n\t\t\t\t// Take over the old connection\n\t\t\t\tnewConns = append(newConns, oldConn)\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\t// New connection didn't exist, so add it to our list of new conns.\n\t\t\tc.infof(\"elastic: %s joined the cluster\", conn.URL())\n\t\t\tnewConns = append(newConns, conn)\n\t\t}\n\t}\n\n\tc.conns = newConns\n\tc.cindex = -1\n\tc.connsMu.Unlock()\n}\n\n// healthchecker periodically runs healthcheck.\nfunc (c *Client) healthchecker() {\n\tc.mu.RLock()\n\ttimeout := c.healthcheckTimeout\n\tinterval := c.healthcheckInterval\n\tc.mu.RUnlock()\n\n\tticker := time.NewTicker(interval)\n\tdefer ticker.Stop()\n\n\tfor {\n\t\tselect {\n\t\tcase <-c.healthcheckStop:\n\t\t\t// we are asked to stop, so we signal back that we're stopping now\n\t\t\tc.healthcheckStop <- true\n\t\t\treturn\n\t\tcase <-ticker.C:\n\t\t\tc.healthcheck(context.Background(), timeout, false)\n\t\t}\n\t}\n}\n\n// healthcheck does a health check on all nodes in the cluster. Depending on\n// the node state, it marks connections as dead, sets them alive etc.\n// If healthchecks are disabled and force is false, this is a no-op.\n// The timeout specifies how long to wait for a response from Elasticsearch.\nfunc (c *Client) healthcheck(parentCtx context.Context, timeout time.Duration, force bool) {\n\tc.mu.RLock()\n\tif !c.healthcheckEnabled && !force {\n\t\tc.mu.RUnlock()\n\t\treturn\n\t}\n\theaders := c.headers\n\tbasicAuth := c.basicAuthUsername != \"\" || c.basicAuthPassword != \"\"\n\tbasicAuthUsername := c.basicAuthUsername\n\tbasicAuthPassword := c.basicAuthPassword\n\tc.mu.RUnlock()\n\n\tc.connsMu.RLock()\n\tconns := c.conns\n\tc.connsMu.RUnlock()\n\n\tfor _, conn := range conns {\n\t\t// Run the HEAD request against ES with a timeout\n\t\tctx, cancel := context.WithTimeout(parentCtx, timeout)\n\t\tdefer cancel()\n\n\t\t// Goroutine executes the HTTP request, returns an error and sets status\n\t\tvar status int\n\t\terrc := make(chan error, 1)\n\t\tgo func(url string) {\n\t\t\treq, err := NewRequest(\"HEAD\", url)\n\t\t\tif err != nil {\n\t\t\t\terrc <- err\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif basicAuth {\n\t\t\t\treq.SetBasicAuth(basicAuthUsername, basicAuthPassword)\n\t\t\t}\n\t\t\tif len(headers) > 0 {\n\t\t\t\tfor key, values := range headers {\n\t\t\t\t\tfor _, v := range values {\n\t\t\t\t\t\treq.Header.Add(key, v)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif req.Header.Get(\"User-Agent\") == \"\" {\n\t\t\t\treq.Header.Add(\"User-Agent\", \"elastic/\"+Version+\" (\"+runtime.GOOS+\"-\"+runtime.GOARCH+\")\")\n\t\t\t}\n\t\t\tres, err := c.c.Do((*http.Request)(req).WithContext(ctx))\n\t\t\tif res != nil {\n\t\t\t\tstatus = res.StatusCode\n\t\t\t\tif res.Body != nil {\n\t\t\t\t\tres.Body.Close()\n\t\t\t\t}\n\t\t\t}\n\t\t\terrc <- err\n\t\t}(conn.URL())\n\n\t\t// Wait for the Goroutine (or its timeout)\n\t\tselect {\n\t\tcase <-ctx.Done(): // timeout\n\t\t\tc.errorf(\"elastic: %s is dead\", conn.URL())\n\t\t\tconn.MarkAsDead()\n\t\tcase err := <-errc:\n\t\t\tif err != nil {\n\t\t\t\tc.errorf(\"elastic: %s is dead\", conn.URL())\n\t\t\t\tconn.MarkAsDead()\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif status >= 200 && status < 300 {\n\t\t\t\tconn.MarkAsAlive()\n\t\t\t} else {\n\t\t\t\tconn.MarkAsDead()\n\t\t\t\tc.errorf(\"elastic: %s is dead [status=%d]\", conn.URL(), status)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// startupHealthcheck is used at startup to check if the server is available\n// at all.\nfunc (c *Client) startupHealthcheck(parentCtx context.Context, timeout time.Duration) error {\n\tc.mu.Lock()\n\turls := c.urls\n\theaders := c.headers\n\tbasicAuth := c.basicAuthUsername != \"\" || c.basicAuthPassword != \"\"\n\tbasicAuthUsername := c.basicAuthUsername\n\tbasicAuthPassword := c.basicAuthPassword\n\tc.mu.Unlock()\n\n\t// If we don't get a connection after \"timeout\", we bail.\n\tvar lastErr error\n\tstart := time.Now()\n\tdone := false\n\tfor !done {\n\t\tfor _, url := range urls {\n\t\t\treq, err := http.NewRequest(\"HEAD\", url, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif basicAuth {\n\t\t\t\treq.SetBasicAuth(basicAuthUsername, basicAuthPassword)\n\t\t\t}\n\t\t\tif len(headers) > 0 {\n\t\t\t\tfor key, values := range headers {\n\t\t\t\t\tfor _, v := range values {\n\t\t\t\t\t\treq.Header.Add(key, v)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tctx, cancel := context.WithTimeout(parentCtx, timeout)\n\t\t\tdefer cancel()\n\t\t\treq = req.WithContext(ctx)\n\t\t\tres, err := c.c.Do(req)\n\t\t\tif err != nil {\n\t\t\t\tlastErr = err\n\t\t\t} else if res.StatusCode >= 200 && res.StatusCode < 300 {\n\t\t\t\treturn nil\n\t\t\t} else if res.StatusCode == http.StatusUnauthorized {\n\t\t\t\tlastErr = &Error{Status: res.StatusCode}\n\t\t\t}\n\t\t}\n\t\tselect {\n\t\tcase <-parentCtx.Done():\n\t\t\tlastErr = parentCtx.Err()\n\t\t\tdone = true\n\t\tcase <-time.After(1 * time.Second):\n\t\t\tif time.Since(start) > timeout {\n\t\t\t\tdone = true\n\t\t\t}\n\t\t}\n\t}\n\tif lastErr != nil {\n\t\tif IsContextErr(lastErr) || IsUnauthorized(lastErr) {\n\t\t\treturn lastErr\n\t\t}\n\t\treturn errors.Wrapf(ErrNoClient, \"health check timeout: %v\", lastErr)\n\t}\n\treturn errors.Wrap(ErrNoClient, \"health check timeout\")\n}\n\n// next returns the next available connection, or ErrNoClient.\nfunc (c *Client) next() (*conn, error) {\n\t// We do round-robin here.\n\t// TODO(oe) This should be a pluggable strategy, like the Selector in the official clients.\n\tc.connsMu.Lock()\n\tdefer c.connsMu.Unlock()\n\n\ti := 0\n\tnumConns := len(c.conns)\n\tfor {\n\t\ti++\n\t\tif i > numConns {\n\t\t\tbreak // we visited all conns: they all seem to be dead\n\t\t}\n\t\tc.cindex++\n\t\tif c.cindex >= numConns {\n\t\t\tc.cindex = 0\n\t\t}\n\t\tconn := c.conns[c.cindex]\n\t\tif !conn.IsDead() {\n\t\t\treturn conn, nil\n\t\t}\n\t}\n\n\t// We have a deadlock here: All nodes are marked as dead.\n\t// If sniffing is disabled, connections will never be marked alive again.\n\t// So we are marking them as alive--if sniffing is disabled.\n\t// They'll then be picked up in the next call to PerformRequest.\n\tif !c.snifferEnabled {\n\t\tc.errorf(\"elastic: all %d nodes marked as dead; resurrecting them to prevent deadlock\", len(c.conns))\n\t\tfor _, conn := range c.conns {\n\t\t\tconn.MarkAsAlive()\n\t\t}\n\t}\n\n\t// We tried hard, but there is no node available\n\treturn nil, errors.Wrap(ErrNoClient, \"no available connection\")\n}\n\n// mustActiveConn returns nil if there is an active connection,\n// otherwise ErrNoClient is returned.\nfunc (c *Client) mustActiveConn() error {\n\tc.connsMu.Lock()\n\tdefer c.connsMu.Unlock()\n\n\tfor _, c := range c.conns {\n\t\tif !c.IsDead() {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn errors.Wrap(ErrNoClient, \"no active connection found\")\n}\n\n// -- PerformRequest --\n\n// PerformRequestOptions must be passed into PerformRequest.\ntype PerformRequestOptions struct {\n\tMethod           string\n\tPath             string\n\tParams           url.Values\n\tBody             interface{}\n\tContentType      string\n\tIgnoreErrors     []int\n\tRetrier          Retrier\n\tRetryStatusCodes []int\n\tHeaders          http.Header\n\tMaxResponseSize  int64\n\tStream           bool\n}\n\n// PerformRequest does a HTTP request to Elasticsearch.\n// It returns a response (which might be nil) and an error on failure.\n//\n// Optionally, a list of HTTP error codes to ignore can be passed.\n// This is necessary for services that expect e.g. HTTP status 404 as a\n// valid outcome (Exists, IndicesExists, IndicesTypeExists).\n//\n// If Stream is set, the returned BodyReader field must be closed, even\n// if PerformRequest returns an error.\nfunc (c *Client) PerformRequest(ctx context.Context, opt PerformRequestOptions) (*Response, error) {\n\tstart := time.Now().UTC()\n\n\tc.mu.RLock()\n\ttimeout := c.healthcheckTimeout\n\tbasicAuth := c.basicAuthUsername != \"\" || c.basicAuthPassword != \"\"\n\tbasicAuthUsername := c.basicAuthUsername\n\tbasicAuthPassword := c.basicAuthPassword\n\tsendGetBodyAs := c.sendGetBodyAs\n\tgzipEnabled := c.gzipEnabled\n\thealthcheckEnabled := c.healthcheckEnabled\n\tretrier := c.retrier\n\tif opt.Retrier != nil {\n\t\tretrier = opt.Retrier\n\t}\n\tretryStatusCodes := c.retryStatusCodes\n\tif opt.RetryStatusCodes != nil {\n\t\tretryStatusCodes = opt.RetryStatusCodes\n\t}\n\tdefaultHeaders := c.headers\n\tc.mu.RUnlock()\n\n\t// retry returns true if statusCode indicates the request is to be retried\n\tretry := func(statusCode int) bool {\n\t\tfor _, code := range retryStatusCodes {\n\t\t\tif code == statusCode {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tvar err error\n\tvar conn *conn\n\tvar req *Request\n\tvar resp *Response\n\tvar retried bool\n\tvar n int\n\n\t// Change method if sendGetBodyAs is specified.\n\tif opt.Method == \"GET\" && opt.Body != nil && sendGetBodyAs != \"GET\" {\n\t\topt.Method = sendGetBodyAs\n\t}\n\n\tfor {\n\t\tpathWithParams := opt.Path\n\t\tif len(opt.Params) > 0 {\n\t\t\tpathWithParams += \"?\" + opt.Params.Encode()\n\t\t}\n\n\t\t// Get a connection\n\t\tconn, err = c.next()\n\t\tif errors.Cause(err) == ErrNoClient {\n\t\t\tn++\n\t\t\tif !retried {\n\t\t\t\t// Force a healtcheck as all connections seem to be dead.\n\t\t\t\tc.healthcheck(ctx, timeout, false)\n\t\t\t\tif healthcheckEnabled {\n\t\t\t\t\tretried = true\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\twait, ok, rerr := retrier.Retry(ctx, n, nil, nil, err)\n\t\t\tif rerr != nil {\n\t\t\t\treturn nil, rerr\n\t\t\t}\n\t\t\tif !ok {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tretried = true\n\t\t\ttime.Sleep(wait)\n\t\t\tcontinue // try again\n\t\t}\n\t\tif err != nil {\n\t\t\tc.errorf(\"elastic: cannot get connection from pool\")\n\t\t\treturn nil, err\n\t\t}\n\n\t\treq, err = NewRequest(opt.Method, conn.URL()+pathWithParams)\n\t\tif err != nil {\n\t\t\tc.errorf(\"elastic: cannot create request for %s %s: %v\", strings.ToUpper(opt.Method), conn.URL()+pathWithParams, err)\n\t\t\treturn nil, err\n\t\t}\n\t\tif basicAuth {\n\t\t\treq.SetBasicAuth(basicAuthUsername, basicAuthPassword)\n\t\t}\n\t\tif opt.ContentType != \"\" {\n\t\t\treq.Header.Set(\"Content-Type\", opt.ContentType)\n\t\t}\n\t\tfor key, value := range opt.Headers {\n\t\t\tfor _, v := range value {\n\t\t\t\treq.Header.Add(key, v)\n\t\t\t}\n\t\t}\n\t\tif len(defaultHeaders) > 0 {\n\t\t\tfor key, value := range defaultHeaders {\n\t\t\t\tfor _, v := range value {\n\t\t\t\t\treq.Header.Add(key, v)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif req.Header.Get(\"User-Agent\") == \"\" {\n\t\t\treq.Header.Set(\"User-Agent\", \"elastic/\"+Version+\" (\"+runtime.GOOS+\"-\"+runtime.GOARCH+\")\")\n\t\t}\n\n\t\t// Set body\n\t\tif opt.Body != nil {\n\t\t\terr = req.SetBody(opt.Body, gzipEnabled)\n\t\t\tif err != nil {\n\t\t\t\tc.errorf(\"elastic: couldn't set body %+v for request: %v\", opt.Body, err)\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\t// Tracing\n\t\tc.dumpRequest((*http.Request)(req))\n\n\t\t// Get response\n\t\tres, err := c.c.Do((*http.Request)(req).WithContext(ctx))\n\t\tif IsContextErr(err) {\n\t\t\t// Proceed, but don't mark the node as dead\n\t\t\treturn nil, err\n\t\t}\n\t\tif err != nil {\n\t\t\tn++\n\t\t\twait, ok, rerr := retrier.Retry(ctx, n, (*http.Request)(req), res, err)\n\t\t\tif rerr != nil {\n\t\t\t\tc.errorf(\"elastic: %s is dead\", conn.URL())\n\t\t\t\tconn.MarkAsDead()\n\t\t\t\treturn nil, rerr\n\t\t\t}\n\t\t\tif !ok {\n\t\t\t\tc.errorf(\"elastic: %s is dead\", conn.URL())\n\t\t\t\tconn.MarkAsDead()\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tretried = true\n\t\t\ttime.Sleep(wait)\n\t\t\tcontinue // try again\n\t\t}\n\t\tif retry(res.StatusCode) {\n\t\t\tn++\n\t\t\twait, ok, rerr := retrier.Retry(ctx, n, (*http.Request)(req), res, err)\n\t\t\tif rerr != nil {\n\t\t\t\tc.errorf(\"elastic: %s is dead\", conn.URL())\n\t\t\t\tconn.MarkAsDead()\n\t\t\t\treturn nil, rerr\n\t\t\t}\n\t\t\tif ok {\n\t\t\t\t// retry\n\t\t\t\tretried = true\n\t\t\t\ttime.Sleep(wait)\n\t\t\t\tcontinue // try again\n\t\t\t}\n\t\t}\n\n\t\tif !opt.Stream {\n\t\t\tdefer res.Body.Close()\n\t\t}\n\n\t\t// Tracing\n\t\tc.dumpResponse(res)\n\n\t\t// Log deprecation warnings as errors\n\t\tif len(res.Header[\"Warning\"]) > 0 {\n\t\t\tc.deprecationlog((*http.Request)(req), res)\n\t\t\tfor _, warning := range res.Header[\"Warning\"] {\n\t\t\t\tc.errorf(\"Deprecation warning: %s\", warning)\n\t\t\t}\n\t\t}\n\n\t\t// Check for errors\n\t\tif err := checkResponse((*http.Request)(req), res, opt.IgnoreErrors...); err != nil {\n\t\t\t// No retry if request succeeded\n\t\t\t// We still try to return a response.\n\t\t\tresp, _ = c.newResponse(res, opt.MaxResponseSize, opt.Stream)\n\t\t\treturn resp, err\n\t\t}\n\n\t\t// We successfully made a request with this connection\n\t\tconn.MarkAsHealthy()\n\n\t\tresp, err = c.newResponse(res, opt.MaxResponseSize, opt.Stream)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tbreak\n\t}\n\n\tduration := time.Now().UTC().Sub(start)\n\tc.infof(\"%s %s [status:%d, request:%.3fs]\",\n\t\tstrings.ToUpper(opt.Method),\n\t\treq.URL.Redacted(),\n\t\tresp.StatusCode,\n\t\tfloat64(int64(duration/time.Millisecond))/1000)\n\n\treturn resp, nil\n}\n\n// -- Document APIs --\n\n// Index a document.\nfunc (c *Client) Index() *IndexService {\n\treturn NewIndexService(c)\n}\n\n// Get a document.\nfunc (c *Client) Get() *GetService {\n\treturn NewGetService(c)\n}\n\n// MultiGet retrieves multiple documents in one roundtrip.\nfunc (c *Client) MultiGet() *MgetService {\n\treturn NewMgetService(c)\n}\n\n// Mget retrieves multiple documents in one roundtrip.\nfunc (c *Client) Mget() *MgetService {\n\treturn NewMgetService(c)\n}\n\n// Delete a document.\nfunc (c *Client) Delete() *DeleteService {\n\treturn NewDeleteService(c)\n}\n\n// DeleteByQuery deletes documents as found by a query.\nfunc (c *Client) DeleteByQuery(indices ...string) *DeleteByQueryService {\n\treturn NewDeleteByQueryService(c).Index(indices...)\n}\n\n// Update a document.\nfunc (c *Client) Update() *UpdateService {\n\treturn NewUpdateService(c)\n}\n\n// UpdateByQuery performs an update on a set of documents.\nfunc (c *Client) UpdateByQuery(indices ...string) *UpdateByQueryService {\n\treturn NewUpdateByQueryService(c).Index(indices...)\n}\n\n// Bulk is the entry point to mass insert/update/delete documents.\nfunc (c *Client) Bulk() *BulkService {\n\treturn NewBulkService(c)\n}\n\n// BulkProcessor allows setting up a concurrent processor of bulk requests.\nfunc (c *Client) BulkProcessor() *BulkProcessorService {\n\treturn NewBulkProcessorService(c)\n}\n\n// Reindex copies data from a source index into a destination index.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-reindex.html\n// for details on the Reindex API.\nfunc (c *Client) Reindex() *ReindexService {\n\treturn NewReindexService(c)\n}\n\n// TermVectors returns information and statistics on terms in the fields\n// of a particular document.\nfunc (c *Client) TermVectors(index string) *TermvectorsService {\n\tbuilder := NewTermvectorsService(c)\n\tbuilder = builder.Index(index)\n\treturn builder\n}\n\n// MultiTermVectors returns information and statistics on terms in the fields\n// of multiple documents.\nfunc (c *Client) MultiTermVectors() *MultiTermvectorService {\n\treturn NewMultiTermvectorService(c)\n}\n\n// -- Search APIs --\n\n// Search is the entry point for searches.\nfunc (c *Client) Search(indices ...string) *SearchService {\n\treturn NewSearchService(c).Index(indices...)\n}\n\n// MultiSearch is the entry point for multi searches.\nfunc (c *Client) MultiSearch() *MultiSearchService {\n\treturn NewMultiSearchService(c)\n}\n\n// Count documents.\nfunc (c *Client) Count(indices ...string) *CountService {\n\treturn NewCountService(c).Index(indices...)\n}\n\n// Explain computes a score explanation for a query and a specific document.\nfunc (c *Client) Explain(index, typ, id string) *ExplainService {\n\treturn NewExplainService(c).Index(index).Type(typ).Id(id)\n}\n\n// TODO Search Template\n// TODO Search Exists API\n\n// Validate allows a user to validate a potentially expensive query without executing it.\nfunc (c *Client) Validate(indices ...string) *ValidateService {\n\treturn NewValidateService(c).Index(indices...)\n}\n\n// SearchShards returns statistical information about nodes and shards.\nfunc (c *Client) SearchShards(indices ...string) *SearchShardsService {\n\treturn NewSearchShardsService(c).Index(indices...)\n}\n\n// FieldCaps returns statistical information about fields in indices.\nfunc (c *Client) FieldCaps(indices ...string) *FieldCapsService {\n\treturn NewFieldCapsService(c).Index(indices...)\n}\n\n// Exists checks if a document exists.\nfunc (c *Client) Exists() *ExistsService {\n\treturn NewExistsService(c)\n}\n\n// Scroll through documents. Use this to efficiently scroll through results\n// while returning the results to a client.\nfunc (c *Client) Scroll(indices ...string) *ScrollService {\n\treturn NewScrollService(c).Index(indices...)\n}\n\n// ClearScroll can be used to clear search contexts manually.\nfunc (c *Client) ClearScroll(scrollIds ...string) *ClearScrollService {\n\treturn NewClearScrollService(c).ScrollId(scrollIds...)\n}\n\n// OpenPointInTime opens a new Point in Time.\nfunc (c *Client) OpenPointInTime(indices ...string) *OpenPointInTimeService {\n\treturn NewOpenPointInTimeService(c).Index(indices...)\n}\n\n// ClosePointInTime closes an existing Point in Time.\nfunc (c *Client) ClosePointInTime(id string) *ClosePointInTimeService {\n\treturn NewClosePointInTimeService(c).ID(id)\n}\n\n// -- Indices APIs --\n\n// CreateIndex returns a service to create a new index.\nfunc (c *Client) CreateIndex(name string) *IndicesCreateService {\n\treturn NewIndicesCreateService(c).Index(name)\n}\n\n// DeleteIndex returns a service to delete an index.\nfunc (c *Client) DeleteIndex(indices ...string) *IndicesDeleteService {\n\treturn NewIndicesDeleteService(c).Index(indices)\n}\n\n// IndexExists allows to check if an index exists.\nfunc (c *Client) IndexExists(indices ...string) *IndicesExistsService {\n\treturn NewIndicesExistsService(c).Index(indices)\n}\n\n// ShrinkIndex returns a service to shrink one index into another.\nfunc (c *Client) ShrinkIndex(source, target string) *IndicesShrinkService {\n\treturn NewIndicesShrinkService(c).Source(source).Target(target)\n}\n\n// RolloverIndex rolls an alias over to a new index when the existing index\n// is considered to be too large or too old.\nfunc (c *Client) RolloverIndex(alias string) *IndicesRolloverService {\n\treturn NewIndicesRolloverService(c).Alias(alias)\n}\n\n// IndexStats provides statistics on different operations happining\n// in one or more indices.\nfunc (c *Client) IndexStats(indices ...string) *IndicesStatsService {\n\treturn NewIndicesStatsService(c).Index(indices...)\n}\n\n// OpenIndex opens an index.\nfunc (c *Client) OpenIndex(name string) *IndicesOpenService {\n\treturn NewIndicesOpenService(c).Index(name)\n}\n\n// CloseIndex closes an index.\nfunc (c *Client) CloseIndex(name string) *IndicesCloseService {\n\treturn NewIndicesCloseService(c).Index(name)\n}\n\n// FreezeIndex freezes an index.\n//\n// Deprecated: Frozen indices are deprecated because they provide no benefit\n// given improvements in heap memory utilization.\nfunc (c *Client) FreezeIndex(name string) *IndicesFreezeService {\n\treturn NewIndicesFreezeService(c).Index(name)\n}\n\n// UnfreezeIndex unfreezes an index.\n//\n// Deprecated: Frozen indices are deprecated because they provide no benefit\n// given improvements in heap memory utilization.\nfunc (c *Client) UnfreezeIndex(name string) *IndicesUnfreezeService {\n\treturn NewIndicesUnfreezeService(c).Index(name)\n}\n\n// IndexGet retrieves information about one or more indices.\n// IndexGet is only available for Elasticsearch 1.4 or later.\nfunc (c *Client) IndexGet(indices ...string) *IndicesGetService {\n\treturn NewIndicesGetService(c).Index(indices...)\n}\n\n// IndexGetSettings retrieves settings of all, one or more indices.\nfunc (c *Client) IndexGetSettings(indices ...string) *IndicesGetSettingsService {\n\treturn NewIndicesGetSettingsService(c).Index(indices...)\n}\n\n// IndexPutSettings sets settings for all, one or more indices.\nfunc (c *Client) IndexPutSettings(indices ...string) *IndicesPutSettingsService {\n\treturn NewIndicesPutSettingsService(c).Index(indices...)\n}\n\n// IndexSegments retrieves low level segment information for all, one or more indices.\nfunc (c *Client) IndexSegments(indices ...string) *IndicesSegmentsService {\n\treturn NewIndicesSegmentsService(c).Index(indices...)\n}\n\n// IndexAnalyze performs the analysis process on a text and returns the\n// token breakdown of the text.\nfunc (c *Client) IndexAnalyze() *IndicesAnalyzeService {\n\treturn NewIndicesAnalyzeService(c)\n}\n\n// Forcemerge optimizes one or more indices.\n// It replaces the deprecated Optimize API.\nfunc (c *Client) Forcemerge(indices ...string) *IndicesForcemergeService {\n\treturn NewIndicesForcemergeService(c).Index(indices...)\n}\n\n// Refresh asks Elasticsearch to refresh one or more indices.\nfunc (c *Client) Refresh(indices ...string) *RefreshService {\n\treturn NewRefreshService(c).Index(indices...)\n}\n\n// Flush asks Elasticsearch to free memory from the index and\n// flush data to disk.\nfunc (c *Client) Flush(indices ...string) *IndicesFlushService {\n\treturn NewIndicesFlushService(c).Index(indices...)\n}\n\n// SyncedFlush performs a synced flush.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-synced-flush.html\n// for more details on synched flushes and how they differ from a normal\n// Flush.\nfunc (c *Client) SyncedFlush(indices ...string) *IndicesSyncedFlushService {\n\treturn NewIndicesSyncedFlushService(c).Index(indices...)\n}\n\n// ClearCache clears caches for one or more indices.\nfunc (c *Client) ClearCache(indices ...string) *IndicesClearCacheService {\n\treturn NewIndicesClearCacheService(c).Index(indices...)\n}\n\n// Alias enables the caller to add and/or remove aliases.\nfunc (c *Client) Alias() *AliasService {\n\treturn NewAliasService(c)\n}\n\n// Aliases returns aliases by index name(s).\nfunc (c *Client) Aliases() *AliasesService {\n\treturn NewAliasesService(c)\n}\n\n// -- Legacy templates --\n\n// IndexGetTemplate gets an index template (v1/legacy version before 7.8).\n//\n// This service implements the legacy version of index templates as described\n// in https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-templates-v1.html.\n//\n// See e.g. IndexPutIndexTemplate and IndexPutComponentTemplate for the new version(s).\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\nfunc (c *Client) IndexGetTemplate(names ...string) *IndicesGetTemplateService {\n\treturn NewIndicesGetTemplateService(c).Name(names...)\n}\n\n// IndexTemplateExists gets check if an index template exists (v1/legacy version before 7.8).\n//\n// This service implements the legacy version of index templates as described\n// in https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-templates-v1.html.\n//\n// See e.g. IndexPutIndexTemplate and IndexPutComponentTemplate for the new version(s).\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\nfunc (c *Client) IndexTemplateExists(name string) *IndicesExistsTemplateService {\n\treturn NewIndicesExistsTemplateService(c).Name(name)\n}\n\n// IndexPutTemplate creates or updates an index template (v1/legacy version before 7.8).\n//\n// This service implements the legacy version of index templates as described\n// in https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-templates-v1.html.\n//\n// See e.g. IndexPutIndexTemplate and IndexPutComponentTemplate for the new version(s).\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\nfunc (c *Client) IndexPutTemplate(name string) *IndicesPutTemplateService {\n\treturn NewIndicesPutTemplateService(c).Name(name)\n}\n\n// IndexDeleteTemplate deletes an index template (v1/legacy version before 7.8).\n//\n// This service implements the legacy version of index templates as described\n// in https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-templates-v1.html.\n//\n// See e.g. IndexPutIndexTemplate and IndexPutComponentTemplate for the new version(s).\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\nfunc (c *Client) IndexDeleteTemplate(name string) *IndicesDeleteTemplateService {\n\treturn NewIndicesDeleteTemplateService(c).Name(name)\n}\n\n// -- Index templates --\n\n// IndexPutIndexTemplate creates or updates an index template (new version after 7.8).\n//\n// This service implements the new version of index templates as described\n// on https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-put-template.html.\n//\n// See e.g. IndexPutTemplate for the v1/legacy version.\nfunc (c *Client) IndexPutIndexTemplate(name string) *IndicesPutIndexTemplateService {\n\treturn NewIndicesPutIndexTemplateService(c).Name(name)\n}\n\n// IndexGetIndexTemplate returns an index template (new version after 7.8).\n//\n// This service implements the new version of index templates as described\n// on https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-get-template.html.\n//\n// See e.g. IndexPutTemplate for the v1/legacy version.\nfunc (c *Client) IndexGetIndexTemplate(name string) *IndicesGetIndexTemplateService {\n\treturn NewIndicesGetIndexTemplateService(c).Name(name)\n}\n\n// IndexDeleteIndexTemplate deletes an index template (new version after 7.8).\n//\n// This service implements the new version of index templates as described\n// on https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-delete-template.html.\n//\n// See e.g. IndexPutTemplate for the v1/legacy version.\nfunc (c *Client) IndexDeleteIndexTemplate(name string) *IndicesDeleteIndexTemplateService {\n\treturn NewIndicesDeleteIndexTemplateService(c).Name(name)\n}\n\n// -- Component templates --\n\n// IndexPutComponentTemplate creates or updates a component template (available since 7.8).\n//\n// This service implements the component templates as described\n// on https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-component-template.html.\nfunc (c *Client) IndexPutComponentTemplate(name string) *IndicesPutComponentTemplateService {\n\treturn NewIndicesPutComponentTemplateService(c).Name(name)\n}\n\n// IndexGetComponentTemplate returns a component template (available since 7.8).\n//\n// This service implements the component templates as described\n// on https://www.elastic.co/guide/en/elasticsearch/reference/7.10/getting-component-templates.html.\nfunc (c *Client) IndexGetComponentTemplate(name string) *IndicesGetComponentTemplateService {\n\treturn NewIndicesGetComponentTemplateService(c).Name(name)\n}\n\n// IndexDeleteComponentTemplate deletes a component template (available since 7.8).\n//\n// This service implements the component templates as described\n// on https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-delete-component-template.html.\nfunc (c *Client) IndexDeleteComponentTemplate(name string) *IndicesDeleteComponentTemplateService {\n\treturn NewIndicesDeleteComponentTemplateService(c).Name(name)\n}\n\n// GetMapping gets a mapping.\nfunc (c *Client) GetMapping() *IndicesGetMappingService {\n\treturn NewIndicesGetMappingService(c)\n}\n\n// PutMapping registers a mapping.\nfunc (c *Client) PutMapping() *IndicesPutMappingService {\n\treturn NewIndicesPutMappingService(c)\n}\n\n// GetFieldMapping gets mapping for fields.\nfunc (c *Client) GetFieldMapping() *IndicesGetFieldMappingService {\n\treturn NewIndicesGetFieldMappingService(c)\n}\n\n// -- cat APIs --\n\n// TODO cat nodes\n// TODO cat pending tasks\n// TODO cat plugins\n// TODO cat recovery\n// TODO cat thread pool\n// TODO cat shards\n// TODO cat segments\n\n// CatMaster returns information about the master node\nfunc (c *Client) CatMaster() *CatMasterService {\n\treturn NewCatMasterService(c)\n}\n\n// CatFielddata returns information about the amount of heap memory currently used by the field data cache.\nfunc (c *Client) CatFielddata() *CatFielddataService {\n\treturn NewCatFielddataService(c)\n}\n\n// CatAliases returns information about aliases.\nfunc (c *Client) CatAliases() *CatAliasesService {\n\treturn NewCatAliasesService(c)\n}\n\n// CatAllocation returns information about the allocation across nodes.\nfunc (c *Client) CatAllocation() *CatAllocationService {\n\treturn NewCatAllocationService(c)\n}\n\n// CatCount returns document counts for indices.\nfunc (c *Client) CatCount() *CatCountService {\n\treturn NewCatCountService(c)\n}\n\n// CatHealth returns information about cluster health.\nfunc (c *Client) CatHealth() *CatHealthService {\n\treturn NewCatHealthService(c)\n}\n\n// CatIndices returns information about indices.\nfunc (c *Client) CatIndices() *CatIndicesService {\n\treturn NewCatIndicesService(c)\n}\n\n// CatShards returns information about shards.\nfunc (c *Client) CatShards() *CatShardsService {\n\treturn NewCatShardsService(c)\n}\n\n// CatSnapshots returns information about snapshots.\nfunc (c *Client) CatSnapshots() *CatSnapshotsService {\n\treturn NewCatSnapshotsService(c)\n}\n\n// -- Ingest APIs --\n\n// IngestPutPipeline adds pipelines and updates existing pipelines in\n// the cluster.\nfunc (c *Client) IngestPutPipeline(id string) *IngestPutPipelineService {\n\treturn NewIngestPutPipelineService(c).Id(id)\n}\n\n// IngestGetPipeline returns pipelines based on ID.\nfunc (c *Client) IngestGetPipeline(ids ...string) *IngestGetPipelineService {\n\treturn NewIngestGetPipelineService(c).Id(ids...)\n}\n\n// IngestDeletePipeline deletes a pipeline by ID.\nfunc (c *Client) IngestDeletePipeline(id string) *IngestDeletePipelineService {\n\treturn NewIngestDeletePipelineService(c).Id(id)\n}\n\n// IngestSimulatePipeline executes a specific pipeline against the set of\n// documents provided in the body of the request.\nfunc (c *Client) IngestSimulatePipeline() *IngestSimulatePipelineService {\n\treturn NewIngestSimulatePipelineService(c)\n}\n\n// -- Cluster APIs --\n\n// ClusterHealth retrieves the health of the cluster.\nfunc (c *Client) ClusterHealth() *ClusterHealthService {\n\treturn NewClusterHealthService(c)\n}\n\n// ClusterReroute allows for manual changes to the allocation of\n// individual shards in the cluster.\nfunc (c *Client) ClusterReroute() *ClusterRerouteService {\n\treturn NewClusterRerouteService(c)\n}\n\n// ClusterState retrieves the state of the cluster.\nfunc (c *Client) ClusterState() *ClusterStateService {\n\treturn NewClusterStateService(c)\n}\n\n// ClusterStats retrieves cluster statistics.\nfunc (c *Client) ClusterStats() *ClusterStatsService {\n\treturn NewClusterStatsService(c)\n}\n\n// NodesInfo retrieves one or more or all of the cluster nodes information.\nfunc (c *Client) NodesInfo() *NodesInfoService {\n\treturn NewNodesInfoService(c)\n}\n\n// NodesStats retrieves one or more or all of the cluster nodes statistics.\nfunc (c *Client) NodesStats() *NodesStatsService {\n\treturn NewNodesStatsService(c)\n}\n\n// TasksCancel cancels tasks running on the specified nodes.\nfunc (c *Client) TasksCancel() *TasksCancelService {\n\treturn NewTasksCancelService(c)\n}\n\n// TasksList retrieves the list of tasks running on the specified nodes.\nfunc (c *Client) TasksList() *TasksListService {\n\treturn NewTasksListService(c)\n}\n\n// TasksGetTask retrieves a task running on the cluster.\nfunc (c *Client) TasksGetTask() *TasksGetTaskService {\n\treturn NewTasksGetTaskService(c)\n}\n\n// TODO Pending cluster tasks\n// TODO Cluster Reroute\n// TODO Cluster Update Settings\n// TODO Nodes Stats\n// TODO Nodes hot_threads\n\n// -- Snapshot and Restore --\n\n// SnapshotStatus returns information about the status of a snapshot.\nfunc (c *Client) SnapshotStatus() *SnapshotStatusService {\n\treturn NewSnapshotStatusService(c)\n}\n\n// SnapshotCreate creates a snapshot.\nfunc (c *Client) SnapshotCreate(repository string, snapshot string) *SnapshotCreateService {\n\treturn NewSnapshotCreateService(c).Repository(repository).Snapshot(snapshot)\n}\n\n// SnapshotCreateRepository creates or updates a snapshot repository.\nfunc (c *Client) SnapshotCreateRepository(repository string) *SnapshotCreateRepositoryService {\n\treturn NewSnapshotCreateRepositoryService(c).Repository(repository)\n}\n\n// SnapshotDelete deletes a snapshot in a snapshot repository.\nfunc (c *Client) SnapshotDelete(repository string, snapshot string) *SnapshotDeleteService {\n\treturn NewSnapshotDeleteService(c).Repository(repository).Snapshot(snapshot)\n}\n\n// SnapshotDeleteRepository deletes a snapshot repository.\nfunc (c *Client) SnapshotDeleteRepository(repositories ...string) *SnapshotDeleteRepositoryService {\n\treturn NewSnapshotDeleteRepositoryService(c).Repository(repositories...)\n}\n\n// SnapshotGetRepository gets a snapshot repository.\nfunc (c *Client) SnapshotGetRepository(repositories ...string) *SnapshotGetRepositoryService {\n\treturn NewSnapshotGetRepositoryService(c).Repository(repositories...)\n}\n\n// SnapshotGet lists snapshot for a repository.\nfunc (c *Client) SnapshotGet(repository string) *SnapshotGetService {\n\treturn NewSnapshotGetService(c).Repository(repository)\n}\n\n// SnapshotVerifyRepository verifies a snapshot repository.\nfunc (c *Client) SnapshotVerifyRepository(repository string) *SnapshotVerifyRepositoryService {\n\treturn NewSnapshotVerifyRepositoryService(c).Repository(repository)\n}\n\n// SnapshotRestore restores the specified indices from a given snapshot\nfunc (c *Client) SnapshotRestore(repository string, snapshot string) *SnapshotRestoreService {\n\treturn NewSnapshotRestoreService(c).Repository(repository).Snapshot(snapshot)\n}\n\n// -- Scripting APIs --\n\n// GetScript reads a stored script in Elasticsearch.\n// Use PutScript for storing a script.\nfunc (c *Client) GetScript() *GetScriptService {\n\treturn NewGetScriptService(c)\n}\n\n// PutScript allows saving a stored script in Elasticsearch.\nfunc (c *Client) PutScript() *PutScriptService {\n\treturn NewPutScriptService(c)\n}\n\n// DeleteScript allows removing a stored script from Elasticsearch.\nfunc (c *Client) DeleteScript() *DeleteScriptService {\n\treturn NewDeleteScriptService(c)\n}\n\n// -- X-Pack General --\n\n// XPackInfo gets information on the xpack plugins enabled on the cluster\n\nfunc (c *Client) XPackInfo() *XPackInfoService {\n\treturn NewXPackInfoService(c)\n}\n\n// -- X-Pack Async Search --\n\n// XPackAsyncSearchSubmit starts an asynchronous search.\nfunc (c *Client) XPackAsyncSearchSubmit() *XPackAsyncSearchSubmit {\n\treturn NewXPackAsyncSearchSubmit(c)\n}\n\n// XPackAsyncSearchGet retrieves the outcome of an asynchronous search.\nfunc (c *Client) XPackAsyncSearchGet() *XPackAsyncSearchGet {\n\treturn NewXPackAsyncSearchGet(c)\n}\n\n// XPackAsyncSearchDelete deletes an asynchronous search.\nfunc (c *Client) XPackAsyncSearchDelete() *XPackAsyncSearchDelete {\n\treturn NewXPackAsyncSearchDelete(c)\n}\n\n// -- X-Pack Index Lifecycle Management --\n\n// XPackIlmPutLifecycle adds or modifies an ilm policy.\nfunc (c *Client) XPackIlmPutLifecycle() *XPackIlmPutLifecycleService {\n\treturn NewXPackIlmPutLifecycleService(c)\n}\n\n// XPackIlmGettLifecycle gets an ilm policy.\nfunc (c *Client) XPackIlmGetLifecycle() *XPackIlmGetLifecycleService {\n\treturn NewXPackIlmGetLifecycleService(c)\n}\n\n// XPackIlmDeleteLifecycle deletes an ilm policy.\nfunc (c *Client) XPackIlmDeleteLifecycle() *XPackIlmDeleteLifecycleService {\n\treturn NewXPackIlmDeleteLifecycleService(c)\n}\n\n// -- X-Pack Security --\n\n// XPackSecurityGetRoleMapping gets a role mapping.\nfunc (c *Client) XPackSecurityGetRoleMapping(roleMappingName string) *XPackSecurityGetRoleMappingService {\n\treturn NewXPackSecurityGetRoleMappingService(c).Name(roleMappingName)\n}\n\n// XPackSecurityPutRoleMapping adds a role mapping.\nfunc (c *Client) XPackSecurityPutRoleMapping(roleMappingName string) *XPackSecurityPutRoleMappingService {\n\treturn NewXPackSecurityPutRoleMappingService(c).Name(roleMappingName)\n}\n\n// XPackSecurityDeleteRoleMapping deletes a role mapping.\nfunc (c *Client) XPackSecurityDeleteRoleMapping(roleMappingName string) *XPackSecurityDeleteRoleMappingService {\n\treturn NewXPackSecurityDeleteRoleMappingService(c).Name(roleMappingName)\n}\n\n// XPackSecurityGetRole gets a role.\nfunc (c *Client) XPackSecurityGetRole(roleName string) *XPackSecurityGetRoleService {\n\treturn NewXPackSecurityGetRoleService(c).Name(roleName)\n}\n\n// XPackSecurityPutRole adds a role.\nfunc (c *Client) XPackSecurityPutRole(roleName string) *XPackSecurityPutRoleService {\n\treturn NewXPackSecurityPutRoleService(c).Name(roleName)\n}\n\n// XPackSecurityDeleteRole deletes a role.\nfunc (c *Client) XPackSecurityDeleteRole(roleName string) *XPackSecurityDeleteRoleService {\n\treturn NewXPackSecurityDeleteRoleService(c).Name(roleName)\n}\n\n// TODO: Clear role cache API\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-clear-role-cache.html\n\n// XPackSecurityChangePassword changes the password of users in the native realm.\nfunc (c *Client) XPackSecurityChangePassword(username string) *XPackSecurityChangePasswordService {\n\treturn NewXPackSecurityChangePasswordService(c).Username(username)\n}\n\n// XPackSecurityGetUser gets details about one or more users.\nfunc (c *Client) XPackSecurityGetUser(usernames ...string) *XPackSecurityGetUserService {\n\treturn NewXPackSecurityGetUserService(c).Usernames(usernames...)\n}\n\n// XPackSecurityPutUser adds or updates a user.\nfunc (c *Client) XPackSecurityPutUser(username string) *XPackSecurityPutUserService {\n\treturn NewXPackSecurityPutUserService(c).Username(username)\n}\n\n// XPackSecurityEnableUser enables a user.\nfunc (c *Client) XPackSecurityEnableUser(username string) *XPackSecurityEnableUserService {\n\treturn NewXPackSecurityEnableUserService(c).Username(username)\n}\n\n// XPackSecurityDisableUser disables a user.\nfunc (c *Client) XPackSecurityDisableUser(username string) *XPackSecurityDisableUserService {\n\treturn NewXPackSecurityDisableUserService(c).Username(username)\n}\n\n// XPackSecurityDeleteUser deletes a user.\nfunc (c *Client) XPackSecurityDeleteUser(username string) *XPackSecurityDeleteUserService {\n\treturn NewXPackSecurityDeleteUserService(c).Username(username)\n}\n\n// -- X-Pack Rollup --\n\n// XPackRollupPut creates or updates a rollup job.\nfunc (c *Client) XPackRollupPut(jobId string) *XPackRollupPutService {\n\treturn NewXPackRollupPutService(c).JobId(jobId)\n}\n\n// XPackRollupGet gets a rollup job.\nfunc (c *Client) XPackRollupGet(jobId string) *XPackRollupGetService {\n\treturn NewXPackRollupGetService(c).JobId(jobId)\n}\n\n// XPackRollupDelete deletes a rollup job.\nfunc (c *Client) XPackRollupDelete(jobId string) *XPackRollupDeleteService {\n\treturn NewXPackRollupDeleteService(c).JobId(jobId)\n}\n\n// XPackRollupStart starts a rollup job.\nfunc (c *Client) XPackRollupStart(jobId string) *XPackRollupStartService {\n\treturn NewXPackRollupStartService(c).JobId(jobId)\n}\n\n// XPackRollupStop stops a rollup job.\nfunc (c *Client) XPackRollupStop(jobId string) *XPackRollupStopService {\n\treturn NewXPackRollupStopService(c).JobId(jobId)\n}\n\n// -- X-Pack Watcher --\n\n// XPackWatchPut adds a watch.\nfunc (c *Client) XPackWatchPut(watchId string) *XPackWatcherPutWatchService {\n\treturn NewXPackWatcherPutWatchService(c).Id(watchId)\n}\n\n// XPackWatchGet gets a watch.\nfunc (c *Client) XPackWatchGet(watchId string) *XPackWatcherGetWatchService {\n\treturn NewXPackWatcherGetWatchService(c).Id(watchId)\n}\n\n// XPackWatchDelete deletes a watch.\nfunc (c *Client) XPackWatchDelete(watchId string) *XPackWatcherDeleteWatchService {\n\treturn NewXPackWatcherDeleteWatchService(c).Id(watchId)\n}\n\n// XPackWatchExecute executes a watch.\nfunc (c *Client) XPackWatchExecute() *XPackWatcherExecuteWatchService {\n\treturn NewXPackWatcherExecuteWatchService(c)\n}\n\n// XPackWatchAck acknowledging a watch.\nfunc (c *Client) XPackWatchAck(watchId string) *XPackWatcherAckWatchService {\n\treturn NewXPackWatcherAckWatchService(c).WatchId(watchId)\n}\n\n// XPackWatchActivate activates a watch.\nfunc (c *Client) XPackWatchActivate(watchId string) *XPackWatcherActivateWatchService {\n\treturn NewXPackWatcherActivateWatchService(c).WatchId(watchId)\n}\n\n// XPackWatchDeactivate deactivates a watch.\nfunc (c *Client) XPackWatchDeactivate(watchId string) *XPackWatcherDeactivateWatchService {\n\treturn NewXPackWatcherDeactivateWatchService(c).WatchId(watchId)\n}\n\n// XPackWatchStats returns the current Watcher metrics.\nfunc (c *Client) XPackWatchStats() *XPackWatcherStatsService {\n\treturn NewXPackWatcherStatsService(c)\n}\n\n// XPackWatchStart starts a watch.\nfunc (c *Client) XPackWatchStart() *XPackWatcherStartService {\n\treturn NewXPackWatcherStartService(c)\n}\n\n// XPackWatchStop stops a watch.\nfunc (c *Client) XPackWatchStop() *XPackWatcherStopService {\n\treturn NewXPackWatcherStopService(c)\n}\n\n// -- Helpers and shortcuts --\n\n// ElasticsearchVersion returns the version number of Elasticsearch\n// running on the given URL.\nfunc (c *Client) ElasticsearchVersion(url string) (string, error) {\n\tres, _, err := c.Ping(url).Do(context.Background())\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn res.Version.Number, nil\n}\n\n// IndexNames returns the names of all indices in the cluster.\nfunc (c *Client) IndexNames() ([]string, error) {\n\tres, err := c.IndexGetSettings().Index(\"_all\").Do(context.Background())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar names []string\n\tfor name := range res {\n\t\tnames = append(names, name)\n\t}\n\treturn names, nil\n}\n\n// Ping checks if a given node in a cluster exists and (optionally)\n// returns some basic information about the Elasticsearch server,\n// e.g. the Elasticsearch version number.\n//\n// Notice that you need to specify a URL here explicitly.\nfunc (c *Client) Ping(url string) *PingService {\n\treturn NewPingService(c).URL(url)\n}\n\n// WaitForStatus waits for the cluster to have the given status.\n// This is a shortcut method for the ClusterHealth service.\n//\n// WaitForStatus waits for the specified timeout, e.g. \"10s\".\n// If the cluster will have the given state within the timeout, nil is returned.\n// If the request timed out, ErrTimeout is returned.\nfunc (c *Client) WaitForStatus(status string, timeout string) error {\n\thealth, err := c.ClusterHealth().WaitForStatus(status).Timeout(timeout).Do(context.Background())\n\tif err != nil {\n\t\treturn err\n\t}\n\tif health.TimedOut {\n\t\treturn ErrTimeout\n\t}\n\treturn nil\n}\n\n// WaitForGreenStatus waits for the cluster to have the \"green\" status.\n// See WaitForStatus for more details.\nfunc (c *Client) WaitForGreenStatus(timeout string) error {\n\treturn c.WaitForStatus(\"green\", timeout)\n}\n\n// WaitForYellowStatus waits for the cluster to have the \"yellow\" status.\n// See WaitForStatus for more details.\nfunc (c *Client) WaitForYellowStatus(timeout string) error {\n\treturn c.WaitForStatus(\"yellow\", timeout)\n}\n"
  },
  {
    "path": "client_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/fortytw2/leaktest\"\n\n\t\"github.com/olivere/elastic/v7/config\"\n)\n\nfunc findConn(s string, slice ...*conn) (int, bool) {\n\tfor i, t := range slice {\n\t\tif s == t.URL() {\n\t\t\treturn i, true\n\t\t}\n\t}\n\treturn -1, false\n}\n\n// -- NewClient --\n\nfunc TestClientDefaults(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif client.healthcheckEnabled != true {\n\t\tt.Errorf(\"expected health checks to be enabled, got: %v\", client.healthcheckEnabled)\n\t}\n\tif client.healthcheckTimeoutStartup != DefaultHealthcheckTimeoutStartup {\n\t\tt.Errorf(\"expected health checks timeout on startup = %v, got: %v\", DefaultHealthcheckTimeoutStartup, client.healthcheckTimeoutStartup)\n\t}\n\tif client.healthcheckTimeout != DefaultHealthcheckTimeout {\n\t\tt.Errorf(\"expected health checks timeout = %v, got: %v\", DefaultHealthcheckTimeout, client.healthcheckTimeout)\n\t}\n\tif client.healthcheckInterval != DefaultHealthcheckInterval {\n\t\tt.Errorf(\"expected health checks interval = %v, got: %v\", DefaultHealthcheckInterval, client.healthcheckInterval)\n\t}\n\tif client.snifferEnabled != true {\n\t\tt.Errorf(\"expected sniffing to be enabled, got: %v\", client.snifferEnabled)\n\t}\n\tif client.snifferTimeoutStartup != DefaultSnifferTimeoutStartup {\n\t\tt.Errorf(\"expected sniffer timeout on startup = %v, got: %v\", DefaultSnifferTimeoutStartup, client.snifferTimeoutStartup)\n\t}\n\tif client.snifferTimeout != DefaultSnifferTimeout {\n\t\tt.Errorf(\"expected sniffer timeout = %v, got: %v\", DefaultSnifferTimeout, client.snifferTimeout)\n\t}\n\tif client.snifferInterval != DefaultSnifferInterval {\n\t\tt.Errorf(\"expected sniffer interval = %v, got: %v\", DefaultSnifferInterval, client.snifferInterval)\n\t}\n\tif client.basicAuthUsername != \"\" {\n\t\tt.Errorf(\"expected no basic auth username; got: %q\", client.basicAuthUsername)\n\t}\n\tif client.basicAuthPassword != \"\" {\n\t\tt.Errorf(\"expected no basic auth password; got: %q\", client.basicAuthUsername)\n\t}\n\tif client.sendGetBodyAs != \"GET\" {\n\t\tt.Errorf(\"expected sendGetBodyAs to be GET; got: %q\", client.sendGetBodyAs)\n\t}\n}\n\nfunc TestClientWithoutURL(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Two things should happen here:\n\t// 1. The client starts sniffing the cluster on DefaultURL\n\t// 2. The sniffing process should find (at least) one node in the cluster, i.e. the DefaultURL\n\tif len(client.conns) == 0 {\n\t\tt.Fatalf(\"expected at least 1 node in the cluster, got: %d (%v)\", len(client.conns), client.conns)\n\t}\n\tif !isCI() {\n\t\tif _, found := findConn(DefaultURL, client.conns...); !found {\n\t\t\tt.Errorf(\"expected to find node with default URL of %s in %v\", DefaultURL, client.conns)\n\t\t}\n\t}\n}\n\nfunc TestClientWithSingleURL(t *testing.T) {\n\tclient, err := NewClient(SetURL(\"http://127.0.0.1:9200\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Two things should happen here:\n\t// 1. The client starts sniffing the cluster on DefaultURL\n\t// 2. The sniffing process should find (at least) one node in the cluster, i.e. the DefaultURL\n\tif len(client.conns) == 0 {\n\t\tt.Fatalf(\"expected at least 1 node in the cluster, got: %d (%v)\", len(client.conns), client.conns)\n\t}\n\tif !isCI() {\n\t\tif _, found := findConn(DefaultURL, client.conns...); !found {\n\t\t\tt.Errorf(\"expected to find node with default URL of %s in %v\", DefaultURL, client.conns)\n\t\t}\n\t}\n}\n\nfunc TestClientWithMultipleURLs(t *testing.T) {\n\tclient, err := NewClient(SetURL(\"http://127.0.0.1:9200\", \"http://127.0.0.1:9201\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// The client should sniff both URLs, but only 127.0.0.1:9200 should return nodes.\n\tif len(client.conns) != 1 {\n\t\tt.Fatalf(\"expected exactly 1 node in the local cluster, got: %d (%v)\", len(client.conns), client.conns)\n\t}\n\tif !isCI() {\n\t\tif client.conns[0].URL() != DefaultURL {\n\t\t\tt.Errorf(\"expected to find node with default URL of %s in %v\", DefaultURL, client.conns)\n\t\t}\n\t}\n}\n\nfunc TestClientWithInvalidURLs(t *testing.T) {\n\tclient, err := NewClient(SetURL(\" http://foo.com\", \"http://[fe80::%31%25en0]:8080/\"))\n\tif err == nil {\n\t\tt.Fatal(\"expected error, got nil\")\n\t}\n\tif want, have := `first path segment in URL cannot contain colon`, err.Error(); !strings.Contains(have, want) {\n\t\tt.Fatalf(\"expected error to contain %q, have %q\", want, have)\n\t}\n\tif client != nil {\n\t\tt.Fatal(\"expected client == nil\")\n\t}\n}\n\nfunc TestClientWithBasicAuth(t *testing.T) {\n\tclient, err := NewClient(SetBasicAuth(\"user\", \"secret\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got, want := client.basicAuthUsername, \"user\"; got != want {\n\t\tt.Errorf(\"expected basic auth username %q; got: %q\", want, got)\n\t}\n\tif got, want := client.basicAuthPassword, \"secret\"; got != want {\n\t\tt.Errorf(\"expected basic auth password %q; got: %q\", want, got)\n\t}\n}\n\nfunc TestClientWithBasicAuthInUserInfo(t *testing.T) {\n\tclient, err := NewClient(SetURL(\"http://user1:secret1@localhost:9200\", \"http://user2:secret2@localhost:9200\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got, want := client.basicAuthUsername, \"user1\"; got != want {\n\t\tt.Errorf(\"expected basic auth username %q; got: %q\", want, got)\n\t}\n\tif got, want := client.basicAuthPassword, \"secret1\"; got != want {\n\t\tt.Errorf(\"expected basic auth password %q; got: %q\", want, got)\n\t}\n}\n\nfunc TestClientWithBasicAuthDuringHealthcheck(t *testing.T) {\n\tts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tif r.Method != \"HEAD\" || r.URL.String() != \"/\" {\n\t\t\tt.Fatalf(\"expected HEAD / request, got %s %s\", r.Method, r.URL)\n\t\t\thttp.Error(w, fmt.Sprintf(\"expected HEAD / request, got %s %s\", r.Method, r.URL), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tusername, password, ok := r.BasicAuth()\n\t\tif !ok {\n\t\t\tt.Fatal(\"expected HEAD basic auth\")\n\t\t\thttp.Error(w, \"expected HTTP basic auth\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tif username != \"user\" && password != \"secret\" {\n\t\t\tt.Fatalf(\"invalid HTTP basic auth username %q and password %q\", username, password)\n\t\t\thttp.Error(w, fmt.Sprintf(\"invalid HTTP basic auth username %q and password %q\", username, password), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tw.WriteHeader(http.StatusOK)\n\t}))\n\tdefer ts.Close()\n\n\tclient, err := NewClient(SetBasicAuth(\"user\", \"secret\"), SetURL(ts.URL), SetSniff(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif client == nil {\n\t\tt.Fatal(\"expected a client\")\n\t}\n}\n\nfunc TestClientWithXpackSecurity(t *testing.T) {\n\t// Connect to ES Platinum with X-Pack Security enabled and L: elastic, P: elastic\n\tclient, err := NewClient(SetURL(\"http://elastic:elastic@127.0.0.1:9210\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got, want := client.basicAuthUsername, \"elastic\"; got != want {\n\t\tt.Errorf(\"expected basic auth username %q; got: %q\", want, got)\n\t}\n\tif got, want := client.basicAuthPassword, \"elastic\"; got != want {\n\t\tt.Errorf(\"expected basic auth password %q; got: %q\", want, got)\n\t}\n}\n\nfunc TestClientWithXpackSecurityUnauthorized(t *testing.T) {\n\tclient, err := NewClient(SetURL(\"http://no-such-user:invalid-password@127.0.0.1:9210\"))\n\tif client != nil {\n\t\tt.Fatal(\"expected no client\")\n\t}\n\tif !IsUnauthorized(err) {\n\t\tt.Fatalf(\"expected IsUnauthorized to be true; got err=%+v\", err)\n\t}\n\tif !IsStatusCode(err, http.StatusUnauthorized) {\n\t\tt.Fatalf(\"expected IsUnauthorized to be true; got err=%+v\", err)\n\t}\n}\n\nfunc TestClientWithoutBasicAuthButAuthEnabledInElasticDuringHealthcheck(t *testing.T) {\n\tts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tif r.Method != \"HEAD\" || r.URL.String() != \"/\" {\n\t\t\tt.Fatalf(\"expected HEAD / request, got %s %s\", r.Method, r.URL)\n\t\t\thttp.Error(w, fmt.Sprintf(\"expected HEAD / request, got %s %s\", r.Method, r.URL), http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\t_, _, ok := r.BasicAuth()\n\t\tif ok {\n\t\t\tt.Fatal(\"unexpected HEAD basic auth\")\n\t\t\thttp.Error(w, \"unexpected HTTP basic auth\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t\tw.WriteHeader(http.StatusUnauthorized)\n\t}))\n\tdefer ts.Close()\n\n\t_, err := NewClient(SetURL(ts.URL), SetSniff(false))\n\tif err == nil {\n\t\tt.Fatal(\"expected unauthorized error\")\n\t}\n\tif !IsUnauthorized(err) {\n\t\tt.Fatalf(\"expected IsUnauthorized = %v, got err=%+v\", true, err)\n\t}\n}\n\nfunc TestClientFromConfig(t *testing.T) {\n\tcfg, err := config.Parse(\"http://127.0.0.1:9200\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tclient, err := NewClientFromConfig(cfg)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Two things should happen here:\n\t// 1. The client starts sniffing the cluster on DefaultURL\n\t// 2. The sniffing process should find (at least) one node in the cluster, i.e. the DefaultURL\n\tif len(client.conns) == 0 {\n\t\tt.Fatalf(\"expected at least 1 node in the cluster, got: %d (%v)\", len(client.conns), client.conns)\n\t}\n\tif !isCI() {\n\t\tif _, found := findConn(DefaultURL, client.conns...); !found {\n\t\t\tt.Errorf(\"expected to find node with default URL of %s in %v\", DefaultURL, client.conns)\n\t\t}\n\t}\n}\n\nfunc TestClientDialFromConfig(t *testing.T) {\n\tcfg, err := config.Parse(\"http://127.0.0.1:9200\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tclient, err := DialWithConfig(context.Background(), cfg)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Two things should happen here:\n\t// 1. The client starts sniffing the cluster on DefaultURL\n\t// 2. The sniffing process should find (at least) one node in the cluster, i.e. the DefaultURL\n\tif len(client.conns) == 0 {\n\t\tt.Fatalf(\"expected at least 1 node in the cluster, got: %d (%v)\", len(client.conns), client.conns)\n\t}\n\tif !isCI() {\n\t\tif _, found := findConn(DefaultURL, client.conns...); !found {\n\t\t\tt.Errorf(\"expected to find node with default URL of %s in %v\", DefaultURL, client.conns)\n\t\t}\n\t}\n}\n\nfunc TestClientDialContext(t *testing.T) {\n\tctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)\n\tdefer cancel()\n\tclient, err := DialContext(ctx, SetURL(\"http://localhost:9200\"))\n\tif err != nil {\n\t\tt.Fatalf(\"expected successful connection, got %v\", err)\n\t}\n\tclient.Stop()\n}\n\nfunc TestClientDialContextTimeoutFromHealthcheck(t *testing.T) {\n\tstart := time.Now().UTC()\n\tctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)\n\tdefer cancel()\n\t_, err := DialContext(ctx, SetURL(\"http://localhost:9299\"), SetHealthcheckTimeoutStartup(5*time.Second))\n\tif !IsContextErr(err) {\n\t\tt.Fatal(err)\n\t}\n\tif time.Since(start) < 3*time.Second {\n\t\tt.Fatalf(\"early timeout\")\n\t}\n\tif time.Since(start) >= 5*time.Second {\n\t\tt.Fatalf(\"timeout probably due to healthcheck, not context cancellation\")\n\t}\n}\n\nfunc TestClientDialContextTimeoutFromSniffer(t *testing.T) {\n\tstart := time.Now().UTC()\n\tctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)\n\tdefer cancel()\n\t_, err := DialContext(ctx, SetURL(\"http://localhost:9299\"), SetHealthcheck(false))\n\tif !IsContextErr(err) {\n\t\tt.Fatal(err)\n\t}\n\tif time.Since(start) < 3*time.Second {\n\t\tt.Fatalf(\"early timeout\")\n\t}\n\tif time.Since(start) >= 5*time.Second {\n\t\tt.Fatalf(\"timeout probably not caused by context cancellation\")\n\t}\n}\n\nfunc TestClientSniffSuccess(t *testing.T) {\n\tclient, err := NewClient(SetURL(\"http://127.0.0.1:19200\", \"http://127.0.0.1:9200\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// The client should sniff both URLs, but only 127.0.0.1:9200 should return nodes.\n\tif len(client.conns) != 1 {\n\t\tt.Fatalf(\"expected exactly 1 node in the local cluster, got: %d (%v)\", len(client.conns), client.conns)\n\t}\n}\n\nfunc TestClientSniffFailure(t *testing.T) {\n\t_, err := NewClient(SetURL(\"http://127.0.0.1:19200\", \"http://127.0.0.1:19201\"))\n\tif err == nil {\n\t\tt.Fatalf(\"expected cluster to fail with no nodes found\")\n\t}\n}\n\nfunc TestClientSnifferCallback(t *testing.T) {\n\tvar calls int\n\tcb := func(node *NodesInfoNode) bool {\n\t\tcalls++\n\t\treturn false\n\t}\n\t_, err := NewClient(\n\t\tSetURL(\"http://127.0.0.1:19200\", \"http://127.0.0.1:9200\"),\n\t\tSetSnifferCallback(cb))\n\tif err == nil {\n\t\tt.Fatalf(\"expected cluster to fail with no nodes found\")\n\t}\n\tif calls != 1 {\n\t\tt.Fatalf(\"expected 1 call to the sniffer callback, got %d\", calls)\n\t}\n}\n\nfunc TestClientSniffDisabled(t *testing.T) {\n\tclient, err := NewClient(SetSniff(false), SetURL(\"http://127.0.0.1:9200\", \"http://127.0.0.1:9201\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// The client should not sniff, so it should have two connections.\n\tif len(client.conns) != 2 {\n\t\tt.Fatalf(\"expected 2 nodes, got: %d (%v)\", len(client.conns), client.conns)\n\t}\n\t// Make two requests, so that both connections are being used\n\tfor i := 0; i < len(client.conns); i++ {\n\t\tclient.Flush().Do(context.TODO())\n\t}\n\t// The first connection (127.0.0.1:9200) should now be okay.\n\tif i, found := findConn(\"http://127.0.0.1:9200\", client.conns...); !found {\n\t\tt.Fatalf(\"expected connection to %q to be found\", \"http://127.0.0.1:9200\")\n\t} else {\n\t\tif conn := client.conns[i]; conn.IsDead() {\n\t\t\tt.Fatal(\"expected connection to be alive, but it is dead\")\n\t\t}\n\t}\n\t// The second connection (127.0.0.1:9201) should now be marked as dead.\n\tif i, found := findConn(\"http://127.0.0.1:9201\", client.conns...); !found {\n\t\tt.Fatalf(\"expected connection to %q to be found\", \"http://127.0.0.1:9201\")\n\t} else {\n\t\tif conn := client.conns[i]; !conn.IsDead() {\n\t\t\tt.Fatal(\"expected connection to be dead, but it is alive\")\n\t\t}\n\t}\n}\n\nfunc TestClientWillMarkConnectionsAsAliveWhenAllAreDead(t *testing.T) {\n\tclient, err := NewClient(SetURL(\"http://127.0.0.1:9201\"),\n\t\tSetSniff(false), SetHealthcheck(false), SetMaxRetries(0))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// We should have a connection.\n\tif len(client.conns) != 1 {\n\t\tt.Fatalf(\"expected 1 node, got: %d (%v)\", len(client.conns), client.conns)\n\t}\n\n\t// Make a request, so that the connections is marked as dead.\n\tclient.Flush().Do(context.TODO())\n\n\t// The connection should now be marked as dead.\n\tif i, found := findConn(\"http://127.0.0.1:9201\", client.conns...); !found {\n\t\tt.Fatalf(\"expected connection to %q to be found\", \"http://127.0.0.1:9201\")\n\t} else {\n\t\tif conn := client.conns[i]; !conn.IsDead() {\n\t\t\tt.Fatalf(\"expected connection to be dead, got: %v\", conn)\n\t\t}\n\t}\n\n\t// Now send another request and the connection should be marked as alive again.\n\tclient.Flush().Do(context.TODO())\n\n\tif i, found := findConn(\"http://127.0.0.1:9201\", client.conns...); !found {\n\t\tt.Fatalf(\"expected connection to %q to be found\", \"http://127.0.0.1:9201\")\n\t} else {\n\t\tif conn := client.conns[i]; conn.IsDead() {\n\t\t\tt.Fatalf(\"expected connection to be alive, got: %v\", conn)\n\t\t}\n\t}\n}\n\nfunc TestClientWithRequiredPlugins(t *testing.T) {\n\t_, err := NewClient(SetRequiredPlugins(\"no-such-plugin\"))\n\tif err == nil {\n\t\tt.Fatal(\"expected error when creating client\")\n\t}\n\tif got, want := err.Error(), \"elastic: plugin no-such-plugin not found\"; got != want {\n\t\tt.Fatalf(\"expected error %q; got: %q\", want, got)\n\t}\n}\n\nfunc TestClientHealthcheckStartupTimeout(t *testing.T) {\n\tstart := time.Now()\n\t_, err := NewClient(SetURL(\"http://localhost:9299\"), SetHealthcheckTimeoutStartup(5*time.Second))\n\tduration := time.Since(start)\n\tif !IsConnErr(err) {\n\t\tt.Fatal(err)\n\t}\n\tif !strings.Contains(err.Error(), \"connection refused\") {\n\t\tt.Fatalf(\"expected error to contain %q, have %q\", \"connection refused\", err.Error())\n\t}\n\tif duration < 5*time.Second {\n\t\tt.Fatalf(\"expected a timeout in more than 5 seconds; got: %v\", duration)\n\t}\n}\n\nfunc TestClientHealthcheckTimeoutLeak(t *testing.T) {\n\t// This test test checks if healthcheck requests are canceled\n\t// after timeout.\n\t// It contains couple of hacks which won't be needed once we\n\t// stop supporting Go1.7.\n\t// On Go1.7 it uses server side effects to monitor if connection\n\t// was closed,\n\t// and on Go 1.8+ we're additionally honestly monitoring routine\n\t// leaks via leaktest.\n\tmux := http.NewServeMux()\n\n\tvar reqDoneMu sync.Mutex\n\tvar reqDone bool\n\tmux.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tcn, ok := w.(http.CloseNotifier)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"Writer is not CloseNotifier, but %v\", reflect.TypeOf(w).Name())\n\t\t}\n\t\t<-cn.CloseNotify()\n\t\treqDoneMu.Lock()\n\t\treqDone = true\n\t\treqDoneMu.Unlock()\n\t})\n\n\tlis, err := net.Listen(\"tcp\", \"127.0.0.1:0\")\n\tif err != nil {\n\t\tt.Fatalf(\"Couldn't setup listener: %v\", err)\n\t}\n\taddr := lis.Addr().String()\n\n\tsrv := &http.Server{\n\t\tHandler: mux,\n\t}\n\tgo srv.Serve(lis)\n\n\tcli := &Client{\n\t\tc: &http.Client{},\n\t\tconns: []*conn{\n\t\t\t{\n\t\t\t\turl: \"http://\" + addr + \"/\",\n\t\t\t},\n\t\t},\n\t}\n\n\ttype closer interface {\n\t\tShutdown(context.Context) error\n\t}\n\n\t// pre-Go1.8 Server can't Shutdown\n\tcl, isServerCloseable := (interface{}(srv)).(closer)\n\n\t// Since Go1.7 can't Shutdown() - there will be leak from server\n\t// Monitor leaks on Go 1.8+\n\tif isServerCloseable {\n\t\tdefer leaktest.CheckTimeout(t, time.Second*10)()\n\t}\n\n\tcli.healthcheck(context.Background(), time.Millisecond*500, true)\n\n\tif isServerCloseable {\n\t\tctx, cancel := context.WithTimeout(context.Background(), time.Second)\n\t\tdefer cancel()\n\t\tcl.Shutdown(ctx)\n\t}\n\n\t<-time.After(time.Second)\n\treqDoneMu.Lock()\n\tif !reqDone {\n\t\treqDoneMu.Unlock()\n\t\tt.Fatal(\"Request wasn't canceled or stopped\")\n\t}\n\treqDoneMu.Unlock()\n}\n\nfunc TestClientSniffUpdatingNodeURL(t *testing.T) {\n\tvar (\n\t\tnodeID  = \"3DWDurZJQvWyWIOFnEB7VA\"\n\t\tnodeURL string\n\t\tn       int\n\t)\n\th := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tn++\n\t\tw.Header().Set(\"Content-Type\", \"application/json\")\n\t\tif r.URL.Path != \"/_nodes/http\" {\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tu, err := url.Parse(nodeURL)\n\t\tif err != nil {\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t\tfmt.Fprintf(w, `{\n\t\t\t\"cluster_name\": \"elasticsearch\",\n\t\t\t\"nodes\": {\n\t\t\t\t%q: {\n\t\t\t\t\t\"name\": \"elasticsearch\",\n\t\t\t\t\t\"http\": {\n\t\t\t\t\t\t\"publish_address\": %q\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}`, nodeID, u.Host)\n\t\tfmt.Fprintln(w)\n\t})\n\tts := httptest.NewServer(h)\n\tdefer ts.Close()\n\n\tnodeURL = ts.URL\n\n\tclient, err := NewSimpleClient(SetURL(ts.URL), SetSniff(true))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif want, have := 0, n; want != have {\n\t\tt.Fatalf(\"expected %d calls to handler; got %d\", want, have)\n\t}\n\tif want, have := 1, len(client.conns); want != have {\n\t\tt.Fatalf(\"expected %d connections; got %d\", want, have)\n\t}\n\tif want, have := nodeURL, client.conns[0].URL(); want != have {\n\t\tt.Fatalf(\"expected URL=%q; got %q\", want, have)\n\t}\n\n\terr = client.sniff(context.Background(), 2*time.Second)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := 1, n; want != have {\n\t\tt.Fatalf(\"expected %d calls to handler; got %d\", want, have)\n\t}\n\tif want, have := 1, len(client.conns); want != have {\n\t\tt.Fatalf(\"expected %d connections; got %d\", want, have)\n\t}\n\tif want, have := nodeID, client.conns[0].NodeID(); want != have {\n\t\tt.Fatalf(\"expected NodeID=%q; got %q\", want, have)\n\t}\n\tif want, have := nodeURL, client.conns[0].URL(); want != have {\n\t\tt.Fatalf(\"expected URL=%q; got %q\", want, have)\n\t}\n\toldNodeID := client.conns[0].NodeID()\n\toldURL := client.conns[0].URL()\n\n\tnodeURL = \"http://127.0.0.1:9999\" // some other nodeURL to report\n\n\terr = client.sniff(context.Background(), 2*time.Second)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := 2, n; want != have {\n\t\tt.Fatalf(\"expected %d calls to handler; got %d\", want, have)\n\t}\n\tif want, have := 1, len(client.conns); want != have {\n\t\tt.Fatalf(\"expected %d connections; got %d\", want, have)\n\t}\n\tnewNodeID := client.conns[0].NodeID()\n\tnewURL := client.conns[0].URL()\n\n\t// NodeID mustn't change\n\tif newNodeID != oldNodeID {\n\t\tt.Fatalf(\"expected NodeID=%q; got %q\", oldNodeID, newNodeID)\n\t}\n\t// URL must have change\n\tif newURL == oldURL {\n\t\tt.Fatalf(\"expected to update URL=%q to %q\", oldURL, newURL)\n\t}\n}\n\n// -- NewSimpleClient --\n\nfunc TestSimpleClientDefaults(t *testing.T) {\n\tclient, err := NewSimpleClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif client.healthcheckEnabled != false {\n\t\tt.Errorf(\"expected health checks to be disabled, got: %v\", client.healthcheckEnabled)\n\t}\n\tif client.healthcheckTimeoutStartup != off {\n\t\tt.Errorf(\"expected health checks timeout on startup = %v, got: %v\", off, client.healthcheckTimeoutStartup)\n\t}\n\tif client.healthcheckTimeout != off {\n\t\tt.Errorf(\"expected health checks timeout = %v, got: %v\", off, client.healthcheckTimeout)\n\t}\n\tif client.healthcheckInterval != off {\n\t\tt.Errorf(\"expected health checks interval = %v, got: %v\", off, client.healthcheckInterval)\n\t}\n\tif client.snifferEnabled != false {\n\t\tt.Errorf(\"expected sniffing to be disabled, got: %v\", client.snifferEnabled)\n\t}\n\tif client.snifferTimeoutStartup != off {\n\t\tt.Errorf(\"expected sniffer timeout on startup = %v, got: %v\", off, client.snifferTimeoutStartup)\n\t}\n\tif client.snifferTimeout != off {\n\t\tt.Errorf(\"expected sniffer timeout = %v, got: %v\", off, client.snifferTimeout)\n\t}\n\tif client.snifferInterval != off {\n\t\tt.Errorf(\"expected sniffer interval = %v, got: %v\", off, client.snifferInterval)\n\t}\n\tif client.basicAuthUsername != \"\" {\n\t\tt.Errorf(\"expected no basic auth username; got: %q\", client.basicAuthUsername)\n\t}\n\tif client.basicAuthPassword != \"\" {\n\t\tt.Errorf(\"expected no basic auth password; got: %q\", client.basicAuthUsername)\n\t}\n\tif client.sendGetBodyAs != \"GET\" {\n\t\tt.Errorf(\"expected sendGetBodyAs to be GET; got: %q\", client.sendGetBodyAs)\n\t}\n}\n\n// -- Start and stop --\n\nfunc TestClientStartAndStop(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\trunning := client.IsRunning()\n\tif !running {\n\t\tt.Fatalf(\"expected background processes to run; got: %v\", running)\n\t}\n\n\t// Stop\n\tclient.Stop()\n\trunning = client.IsRunning()\n\tif running {\n\t\tt.Fatalf(\"expected background processes to be stopped; got: %v\", running)\n\t}\n\n\t// Stop again => no-op\n\tclient.Stop()\n\trunning = client.IsRunning()\n\tif running {\n\t\tt.Fatalf(\"expected background processes to be stopped; got: %v\", running)\n\t}\n\n\t// Start\n\tclient.Start()\n\trunning = client.IsRunning()\n\tif !running {\n\t\tt.Fatalf(\"expected background processes to run; got: %v\", running)\n\t}\n\n\t// Start again => no-op\n\tclient.Start()\n\trunning = client.IsRunning()\n\tif !running {\n\t\tt.Fatalf(\"expected background processes to run; got: %v\", running)\n\t}\n}\n\nfunc TestClientStartAndStopWithSnifferAndHealthchecksDisabled(t *testing.T) {\n\tclient, err := NewClient(SetSniff(false), SetHealthcheck(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\trunning := client.IsRunning()\n\tif !running {\n\t\tt.Fatalf(\"expected background processes to run; got: %v\", running)\n\t}\n\n\t// Stop\n\tclient.Stop()\n\trunning = client.IsRunning()\n\tif running {\n\t\tt.Fatalf(\"expected background processes to be stopped; got: %v\", running)\n\t}\n\n\t// Stop again => no-op\n\tclient.Stop()\n\trunning = client.IsRunning()\n\tif running {\n\t\tt.Fatalf(\"expected background processes to be stopped; got: %v\", running)\n\t}\n\n\t// Start\n\tclient.Start()\n\trunning = client.IsRunning()\n\tif !running {\n\t\tt.Fatalf(\"expected background processes to run; got: %v\", running)\n\t}\n\n\t// Start again => no-op\n\tclient.Start()\n\trunning = client.IsRunning()\n\tif !running {\n\t\tt.Fatalf(\"expected background processes to run; got: %v\", running)\n\t}\n}\n\n// -- Sniffing --\n\nfunc TestClientSniffNode(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tch := make(chan []*conn)\n\tgo func() { ch <- client.sniffNode(context.Background(), DefaultURL) }()\n\n\tselect {\n\tcase nodes := <-ch:\n\t\tif len(nodes) != 1 {\n\t\t\tt.Fatalf(\"expected %d nodes; got: %d\", 1, len(nodes))\n\t\t}\n\t\tpattern := `http:\\/\\/[\\d\\.]+:9200`\n\t\tmatched, err := regexp.MatchString(pattern, nodes[0].URL())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif !matched {\n\t\t\tt.Fatalf(\"expected node URL pattern %q; got: %q\", pattern, nodes[0].URL())\n\t\t}\n\tcase <-time.After(2 * time.Second):\n\t\tt.Fatal(\"expected no timeout in sniff node\")\n\t\tbreak\n\t}\n}\n\nfunc TestClientSniffOnDefaultURL(t *testing.T) {\n\tclient, _ := NewClient()\n\tif client == nil {\n\t\tt.Fatal(\"no client returned\")\n\t}\n\n\tch := make(chan error, 1)\n\tgo func() {\n\t\tch <- client.sniff(context.Background(), DefaultSnifferTimeoutStartup)\n\t}()\n\n\tselect {\n\tcase err := <-ch:\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected sniff to succeed; got: %v\", err)\n\t\t}\n\t\tif len(client.conns) != 1 {\n\t\t\tt.Fatalf(\"expected %d nodes; got: %d\", 1, len(client.conns))\n\t\t}\n\t\tpattern := `http:\\/\\/[\\d\\.]+:9200`\n\t\tmatched, err := regexp.MatchString(pattern, client.conns[0].URL())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif !matched {\n\t\t\tt.Fatalf(\"expected node URL pattern %q; got: %q\", pattern, client.conns[0].URL())\n\t\t}\n\tcase <-time.After(2 * time.Second):\n\t\tt.Fatal(\"expected no timeout in sniff\")\n\t\tbreak\n\t}\n}\n\nfunc TestClientSniffTimeoutLeak(t *testing.T) {\n\t// This test test checks if sniff requests are canceled\n\t// after timeout.\n\t// It contains couple of hacks which won't be needed once we\n\t// stop supporting Go1.7.\n\t// On Go1.7 it uses server side effects to monitor if connection\n\t// was closed,\n\t// and on Go 1.8+ we're additionally honestly monitoring routine\n\t// leaks via leaktest.\n\tmux := http.NewServeMux()\n\n\tvar reqDoneMu sync.Mutex\n\tvar reqDone bool\n\tmux.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tcn, ok := w.(http.CloseNotifier)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"Writer is not CloseNotifier, but %v\", reflect.TypeOf(w).Name())\n\t\t}\n\t\t<-cn.CloseNotify()\n\t\treqDoneMu.Lock()\n\t\treqDone = true\n\t\treqDoneMu.Unlock()\n\t})\n\n\tlis, err := net.Listen(\"tcp\", \"127.0.0.1:0\")\n\tif err != nil {\n\t\tt.Fatalf(\"Couldn't setup listener: %v\", err)\n\t}\n\taddr := lis.Addr().String()\n\n\tsrv := &http.Server{\n\t\tHandler: mux,\n\t}\n\tgo srv.Serve(lis)\n\n\tcli := &Client{\n\t\tc: &http.Client{},\n\t\tconns: []*conn{\n\t\t\t{\n\t\t\t\turl: \"http://\" + addr + \"/\",\n\t\t\t},\n\t\t},\n\t\tsnifferEnabled: true,\n\t}\n\n\ttype closer interface {\n\t\tShutdown(context.Context) error\n\t}\n\n\t// pre-Go1.8 Server can't Shutdown\n\tcl, isServerCloseable := (interface{}(srv)).(closer)\n\n\t// Since Go1.7 can't Shutdown() - there will be leak from server\n\t// Monitor leaks on Go 1.8+\n\tif isServerCloseable {\n\t\tdefer leaktest.CheckTimeout(t, time.Second*10)()\n\t}\n\n\tcli.sniff(context.Background(), time.Millisecond*500)\n\n\tif isServerCloseable {\n\t\tctx, cancel := context.WithTimeout(context.Background(), time.Second)\n\t\tdefer cancel()\n\t\tcl.Shutdown(ctx)\n\t}\n\n\t<-time.After(time.Second)\n\treqDoneMu.Lock()\n\tif !reqDone {\n\t\treqDoneMu.Unlock()\n\t\tt.Fatal(\"Request wasn't canceled or stopped\")\n\t}\n\treqDoneMu.Unlock()\n}\n\nfunc TestClientExtractHostname(t *testing.T) {\n\ttests := []struct {\n\t\tScheme  string\n\t\tAddress string\n\t\tOutput  string\n\t}{\n\t\t{\n\t\t\tScheme:  \"http\",\n\t\t\tAddress: \"127.0.0.1:9200\",\n\t\t\tOutput:  \"http://127.0.0.1:9200\",\n\t\t},\n\t\t{\n\t\t\tScheme:  \"https\",\n\t\t\tAddress: \"127.0.0.1:9200\",\n\t\t\tOutput:  \"https://127.0.0.1:9200\",\n\t\t},\n\t\t{\n\t\t\tScheme:  \"http\",\n\t\t\tAddress: \"127.0.0.1:19200\",\n\t\t\tOutput:  \"http://127.0.0.1:19200\",\n\t\t},\n\t\t{\n\t\t\tScheme:  \"http\",\n\t\t\tAddress: \"myelk.local/10.1.0.24:9200\",\n\t\t\tOutput:  \"http://myelk.local:9200\",\n\t\t},\n\t}\n\n\tclient, err := NewClient(SetSniff(false), SetHealthcheck(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor _, test := range tests {\n\t\tgot := client.extractHostname(test.Scheme, test.Address)\n\t\tif want := test.Output; want != got {\n\t\t\tt.Errorf(\"expected %q; got: %q\", want, got)\n\t\t}\n\t}\n}\n\n// -- Selector --\n\nfunc TestClientSelectConnHealthy(t *testing.T) {\n\tclient, err := NewClient(\n\t\tSetSniff(false),\n\t\tSetHealthcheck(false),\n\t\tSetURL(\"http://127.0.0.1:9200\", \"http://127.0.0.1:9201\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Both are healthy, so we should get both URLs in round-robin\n\tclient.conns[0].MarkAsHealthy()\n\tclient.conns[1].MarkAsHealthy()\n\n\t// #1: Return 1st\n\tc, err := client.next()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.URL() != client.conns[0].URL() {\n\t\tt.Fatalf(\"expected %s; got: %s\", c.URL(), client.conns[0].URL())\n\t}\n\t// #2: Return 2nd\n\tc, err = client.next()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.URL() != client.conns[1].URL() {\n\t\tt.Fatalf(\"expected %s; got: %s\", c.URL(), client.conns[1].URL())\n\t}\n\t// #3: Return 1st\n\tc, err = client.next()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.URL() != client.conns[0].URL() {\n\t\tt.Fatalf(\"expected %s; got: %s\", c.URL(), client.conns[0].URL())\n\t}\n}\n\nfunc TestClientSelectConnHealthyAndDead(t *testing.T) {\n\tclient, err := NewClient(\n\t\tSetSniff(false),\n\t\tSetHealthcheck(false),\n\t\tSetURL(\"http://127.0.0.1:9200\", \"http://127.0.0.1:9201\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// 1st is healthy, second is dead\n\tclient.conns[0].MarkAsHealthy()\n\tclient.conns[1].MarkAsDead()\n\n\t// #1: Return 1st\n\tc, err := client.next()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.URL() != client.conns[0].URL() {\n\t\tt.Fatalf(\"expected %s; got: %s\", c.URL(), client.conns[0].URL())\n\t}\n\t// #2: Return 1st again\n\tc, err = client.next()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.URL() != client.conns[0].URL() {\n\t\tt.Fatalf(\"expected %s; got: %s\", c.URL(), client.conns[0].URL())\n\t}\n\t// #3: Return 1st again and again\n\tc, err = client.next()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.URL() != client.conns[0].URL() {\n\t\tt.Fatalf(\"expected %s; got: %s\", c.URL(), client.conns[0].URL())\n\t}\n}\n\nfunc TestClientSelectConnDeadAndHealthy(t *testing.T) {\n\tclient, err := NewClient(\n\t\tSetSniff(false),\n\t\tSetHealthcheck(false),\n\t\tSetURL(\"http://127.0.0.1:9200\", \"http://127.0.0.1:9201\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// 1st is dead, 2nd is healthy\n\tclient.conns[0].MarkAsDead()\n\tclient.conns[1].MarkAsHealthy()\n\n\t// #1: Return 2nd\n\tc, err := client.next()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.URL() != client.conns[1].URL() {\n\t\tt.Fatalf(\"expected %s; got: %s\", c.URL(), client.conns[1].URL())\n\t}\n\t// #2: Return 2nd again\n\tc, err = client.next()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.URL() != client.conns[1].URL() {\n\t\tt.Fatalf(\"expected %s; got: %s\", c.URL(), client.conns[1].URL())\n\t}\n\t// #3: Return 2nd again and again\n\tc, err = client.next()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif c.URL() != client.conns[1].URL() {\n\t\tt.Fatalf(\"expected %s; got: %s\", c.URL(), client.conns[1].URL())\n\t}\n}\n\nfunc TestClientSelectConnAllDead(t *testing.T) {\n\tclient, err := NewClient(\n\t\tSetSniff(false),\n\t\tSetHealthcheck(false),\n\t\tSetURL(\"http://127.0.0.1:9200\", \"http://127.0.0.1:9201\"))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Both are dead\n\tclient.conns[0].MarkAsDead()\n\tclient.conns[1].MarkAsDead()\n\n\t// If all connections are dead, next should make them alive again, but\n\t// still return an error when it first finds out.\n\tc, err := client.next()\n\tif !IsConnErr(err) {\n\t\tt.Fatal(err)\n\t}\n\tif c != nil {\n\t\tt.Fatalf(\"expected no connection; got: %v\", c)\n\t}\n\t// Return a connection\n\tc, err = client.next()\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif c == nil {\n\t\tt.Fatalf(\"expected connection; got: %v\", c)\n\t}\n\t// Return a connection\n\tc, err = client.next()\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif c == nil {\n\t\tt.Fatalf(\"expected connection; got: %v\", c)\n\t}\n}\n\n// -- ElasticsearchVersion --\n\nfunc TestElasticsearchVersion(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tversion, err := client.ElasticsearchVersion(DefaultURL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif version == \"\" {\n\t\tt.Errorf(\"expected a version number, got: %q\", version)\n\t}\n}\n\n// -- IndexNames --\n\nfunc TestIndexNames(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\tnames, err := client.IndexNames()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(names) == 0 {\n\t\tt.Fatalf(\"expected some index names, got: %d\", len(names))\n\t}\n\tvar found bool\n\tfor _, name := range names {\n\t\tif name == testIndexName {\n\t\t\tfound = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !found {\n\t\tt.Fatalf(\"expected to find index %q; got: %v\", testIndexName, found)\n\t}\n}\n\n// -- PerformRequest --\n\nfunc TestPerformRequest(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\n\tret := new(PingResult)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\tt.Fatalf(\"expected no error on decode; got: %v\", err)\n\t}\n\tif ret.ClusterName == \"\" {\n\t\tt.Errorf(\"expected cluster name; got: %q\", ret.ClusterName)\n\t}\n}\n\nfunc TestPerformRequestWithStream(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t\tStream: true,\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\tif res.BodyReader == nil {\n\t\tt.Fatal(\"expected res.BodyReader to be != nil\")\n\t}\n\tif res.Body != nil {\n\t\tt.Fatal(\"expected res.Body to be == nil\")\n\t}\n\n\tret := new(PingResult)\n\tif err := json.NewDecoder(res.BodyReader).Decode(ret); err != nil {\n\t\tt.Fatalf(\"expected no error on decode; got: %v\", err)\n\t}\n\tif ret.ClusterName == \"\" {\n\t\tt.Errorf(\"expected cluster name; got: %q\", ret.ClusterName)\n\t}\n}\n\nfunc TestPerformRequestWithSimpleClient(t *testing.T) {\n\tclient, err := NewSimpleClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\n\tret := new(PingResult)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\tt.Fatalf(\"expected no error on decode; got: %v\", err)\n\t}\n\tif ret.ClusterName == \"\" {\n\t\tt.Errorf(\"expected cluster name; got: %q\", ret.ClusterName)\n\t}\n}\n\nfunc TestPerformRequestWithLogger(t *testing.T) {\n\tvar w bytes.Buffer\n\tout := log.New(&w, \"LOGGER \", log.LstdFlags)\n\n\tclient, err := NewClient(SetInfoLog(out), SetSniff(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\n\tret := new(PingResult)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\tt.Fatalf(\"expected no error on decode; got: %v\", err)\n\t}\n\tif ret.ClusterName == \"\" {\n\t\tt.Errorf(\"expected cluster name; got: %q\", ret.ClusterName)\n\t}\n\n\tgot := w.String()\n\tpattern := `^LOGGER \\d{4}/\\d{2}/\\d{2} \\d{2}:\\d{2}:\\d{2} GET http://.*/ \\[status:200, request:\\d+\\.\\d{3}s\\]\\n`\n\tmatched, err := regexp.MatchString(pattern, got)\n\tif err != nil {\n\t\tt.Fatalf(\"expected log line to match %q; got: %v\", pattern, err)\n\t}\n\tif !matched {\n\t\tt.Errorf(\"expected log line to match %q; got: %v\", pattern, got)\n\t}\n}\n\nfunc TestPerformRequestWithLoggerAndTracer(t *testing.T) {\n\tvar lw bytes.Buffer\n\tlout := log.New(&lw, \"LOGGER \", log.LstdFlags)\n\n\tvar tw bytes.Buffer\n\ttout := log.New(&tw, \"TRACER \", log.LstdFlags)\n\n\tclient, err := NewClient(SetInfoLog(lout), SetTraceLog(tout), SetSniff(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\n\tret := new(PingResult)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\tt.Fatalf(\"expected no error on decode; got: %v\", err)\n\t}\n\tif ret.ClusterName == \"\" {\n\t\tt.Errorf(\"expected cluster name; got: %q\", ret.ClusterName)\n\t}\n\n\tlgot := lw.String()\n\tif lgot == \"\" {\n\t\tt.Errorf(\"expected logger output; got: %q\", lgot)\n\t}\n\n\ttgot := tw.String()\n\tif tgot == \"\" {\n\t\tt.Errorf(\"expected tracer output; got: %q\", tgot)\n\t}\n}\nfunc TestPerformRequestWithTracerOnError(t *testing.T) {\n\tvar tw bytes.Buffer\n\ttout := log.New(&tw, \"TRACER \", log.LstdFlags)\n\n\tclient, err := NewClient(SetTraceLog(tout), SetSniff(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tclient.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/no-such-index\",\n\t})\n\n\ttgot := tw.String()\n\tif tgot == \"\" {\n\t\tt.Errorf(\"expected tracer output; got: %q\", tgot)\n\t}\n}\n\ntype customLogger struct {\n\tout bytes.Buffer\n}\n\nfunc (l *customLogger) Printf(format string, v ...interface{}) {\n\tl.out.WriteString(fmt.Sprintf(format, v...) + \"\\n\")\n}\n\nfunc TestPerformRequestWithCustomLogger(t *testing.T) {\n\tlogger := &customLogger{}\n\n\tclient, err := NewClient(SetInfoLog(logger), SetSniff(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\n\tret := new(PingResult)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\tt.Fatalf(\"expected no error on decode; got: %v\", err)\n\t}\n\tif ret.ClusterName == \"\" {\n\t\tt.Errorf(\"expected cluster name; got: %q\", ret.ClusterName)\n\t}\n\n\tgot := logger.out.String()\n\tpattern := `^GET http://.*/ \\[status:200, request:\\d+\\.\\d{3}s\\]\\n`\n\tmatched, err := regexp.MatchString(pattern, got)\n\tif err != nil {\n\t\tt.Fatalf(\"expected log line to match %q; got: %v\", pattern, err)\n\t}\n\tif !matched {\n\t\tt.Errorf(\"expected log line to match %q; got: %v\", pattern, got)\n\t}\n}\n\nfunc TestPerformRequestWithMaxResponseSize(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod:          \"GET\",\n\t\tPath:            \"/\",\n\t\tMaxResponseSize: 1000,\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\n\t_, err = client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod:          \"GET\",\n\t\tPath:            \"/\",\n\t\tMaxResponseSize: 100,\n\t})\n\tif err != ErrResponseSize {\n\t\tt.Fatal(\"expected response size error\")\n\t}\n}\n\nfunc TestPerformRequestOnNoConnectionsWithHealthcheckRevival(t *testing.T) {\n\tfail := func(r *http.Request) (*http.Response, error) {\n\t\treturn nil, errors.New(\"request failed\")\n\t}\n\ttr := &failingTransport{path: \"/fail\", fail: fail}\n\thttpClient := &http.Client{Transport: tr}\n\tclient, err := NewClient(SetHttpClient(httpClient), SetMaxRetries(0), SetHealthcheck(true))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Run against a failing endpoint to mark connection as dead\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/fail\",\n\t})\n\tif err == nil {\n\t\tt.Fatal(err)\n\t}\n\tif res != nil {\n\t\tt.Fatal(\"expected no response\")\n\t}\n\n\t// Forced healthcheck should bring connection back to life and complete request\n\tres, err = client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n}\n\n// failingTransport will run a fail callback if it sees a given URL path prefix.\ntype failingTransport struct {\n\tpath string                                      // path prefix to look for\n\tfail func(*http.Request) (*http.Response, error) // call when path prefix is found\n\tnext http.RoundTripper                           // next round-tripper (use http.DefaultTransport if nil)\n}\n\n// RoundTrip implements a failing transport.\nfunc (tr *failingTransport) RoundTrip(r *http.Request) (*http.Response, error) {\n\tif strings.HasPrefix(r.URL.Path, tr.path) && tr.fail != nil {\n\t\treturn tr.fail(r)\n\t}\n\tif tr.next != nil {\n\t\treturn tr.next.RoundTrip(r)\n\t}\n\treturn http.DefaultTransport.RoundTrip(r)\n}\n\nfunc TestPerformRequestRetryOnHttpError(t *testing.T) {\n\tvar numFailedReqs int\n\tfail := func(r *http.Request) (*http.Response, error) {\n\t\tnumFailedReqs += 1\n\t\treturn nil, errors.New(\"request failed\")\n\t}\n\n\t// Run against a failing endpoint and see if PerformRequest\n\t// retries correctly.\n\ttr := &failingTransport{path: \"/fail\", fail: fail}\n\thttpClient := &http.Client{Transport: tr}\n\n\tclient, err := NewClient(SetHttpClient(httpClient), SetMaxRetries(5), SetHealthcheck(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/fail\",\n\t})\n\tif err == nil {\n\t\tt.Fatal(\"expected error\")\n\t}\n\tif res != nil {\n\t\tt.Fatal(\"expected no response\")\n\t}\n\t// Connection should be marked as dead after it failed\n\tif numFailedReqs != 5 {\n\t\tt.Errorf(\"expected %d failed requests; got: %d\", 5, numFailedReqs)\n\t}\n}\n\nfunc TestPerformRequestNoRetryOnValidButUnsuccessfulHttpStatus(t *testing.T) {\n\tvar numFailedReqs int\n\tfail := func(r *http.Request) (*http.Response, error) {\n\t\tnumFailedReqs++\n\t\treturn &http.Response{Request: r, StatusCode: 500, Body: http.NoBody}, nil\n\t}\n\n\t// Run against a failing endpoint and see if PerformRequest\n\t// retries correctly.\n\ttr := &failingTransport{path: \"/fail\", fail: fail}\n\thttpClient := &http.Client{Transport: tr}\n\n\tclient, err := NewClient(SetHttpClient(httpClient), SetMaxRetries(5), SetHealthcheck(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/fail\",\n\t})\n\tif err == nil {\n\t\tt.Fatal(\"expected error\")\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response, got nil\")\n\t}\n\tif want, got := 500, res.StatusCode; want != got {\n\t\tt.Fatalf(\"expected status code = %d, got %d\", want, got)\n\t}\n\t// Retry should not have triggered additional requests because\n\tif numFailedReqs != 1 {\n\t\tt.Errorf(\"expected %d failed requests; got: %d\", 1, numFailedReqs)\n\t}\n}\n\nfunc TestPerformRequestOnSpecifiedHttpStatusCodes(t *testing.T) {\n\tvar numFailedReqs int\n\tfail := func(r *http.Request) (*http.Response, error) {\n\t\tnumFailedReqs++\n\t\treturn &http.Response{Request: r, StatusCode: 429, Body: http.NoBody}, nil\n\t}\n\n\t// Run against a failing endpoint and see if PerformRequest\n\t// retries correctly.\n\ttr := &failingTransport{path: \"/fail\", fail: fail}\n\thttpClient := &http.Client{Transport: tr}\n\n\tclient, err := NewClient(\n\t\tSetHttpClient(httpClient),\n\t\tSetMaxRetries(5),\n\t\tSetRetryStatusCodes(429, 504),\n\t\tSetHealthcheck(false),\n\t)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/fail\",\n\t})\n\tif err == nil {\n\t\tt.Fatalf(\"expected error: err=%v, resp=%+v\", err, res)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response, got nil\")\n\t}\n\tif want, got := 429, res.StatusCode; want != got {\n\t\tt.Fatalf(\"expected status code = %d, got %d\", want, got)\n\t}\n\t// Retry should not have triggered additional requests because\n\tif numFailedReqs != 5 {\n\t\tt.Errorf(\"expected %d failed requests; got: %d\", 1, numFailedReqs)\n\t}\n}\n\n// failingBody will return an error when json.Marshal is called on it.\ntype failingBody struct{}\n\n// MarshalJSON implements the json.Marshaler interface and always returns an error.\nfunc (fb failingBody) MarshalJSON() ([]byte, error) {\n\treturn nil, errors.New(\"failing to marshal\")\n}\n\nfunc TestPerformRequestWithSetBodyError(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t\tBody:   failingBody{},\n\t})\n\tif err == nil {\n\t\tt.Fatal(\"expected error\")\n\t}\n\tif res != nil {\n\t\tt.Fatal(\"expected no response\")\n\t}\n}\n\n// sleepingTransport will sleep before doing a request.\ntype sleepingTransport struct {\n\ttimeout time.Duration\n}\n\n// RoundTrip implements a \"sleepy\" transport.\nfunc (tr *sleepingTransport) RoundTrip(r *http.Request) (*http.Response, error) {\n\ttime.Sleep(tr.timeout)\n\treturn http.DefaultTransport.RoundTrip(r)\n}\n\nfunc TestPerformRequestWithCancel(t *testing.T) {\n\ttr := &sleepingTransport{timeout: 3 * time.Second}\n\thttpClient := &http.Client{Transport: tr}\n\n\tclient, err := NewSimpleClient(SetHttpClient(httpClient), SetMaxRetries(0))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttype result struct {\n\t\tres *Response\n\t\terr error\n\t}\n\tctx, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\tresc := make(chan result, 1)\n\tgo func() {\n\t\tres, err := client.PerformRequest(ctx, PerformRequestOptions{\n\t\t\tMethod: \"GET\",\n\t\t\tPath:   \"/\",\n\t\t})\n\t\tresc <- result{res: res, err: err}\n\t}()\n\tselect {\n\tcase <-time.After(1 * time.Second):\n\t\tcancel()\n\tcase res := <-resc:\n\t\tt.Fatalf(\"expected response before cancel, got %v\", res)\n\tcase <-ctx.Done():\n\t\tt.Fatalf(\"expected no early termination, got ctx.Done(): %v\", ctx.Err())\n\t}\n\terr = ctx.Err()\n\tif err != context.Canceled {\n\t\tt.Fatalf(\"expected error context.Canceled, got: %v\", err)\n\t}\n}\n\nfunc TestPerformRequestWithTimeout(t *testing.T) {\n\ttr := &sleepingTransport{timeout: 3 * time.Second}\n\thttpClient := &http.Client{Transport: tr}\n\n\tclient, err := NewSimpleClient(SetHttpClient(httpClient), SetMaxRetries(0))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttype result struct {\n\t\tres *Response\n\t\terr error\n\t}\n\tctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)\n\tdefer cancel()\n\n\tresc := make(chan result, 1)\n\tgo func() {\n\t\tres, err := client.PerformRequest(ctx, PerformRequestOptions{\n\t\t\tMethod: \"GET\",\n\t\t\tPath:   \"/\",\n\t\t})\n\t\tresc <- result{res: res, err: err}\n\t}()\n\tselect {\n\tcase res := <-resc:\n\t\tt.Fatalf(\"expected timeout before response, got %v\", res)\n\tcase <-ctx.Done():\n\t\terr := ctx.Err()\n\t\tif err != context.DeadlineExceeded {\n\t\t\tt.Fatalf(\"expected error context.DeadlineExceeded, got: %v\", err)\n\t\t}\n\t}\n}\n\nfunc TestPerformRequestWithCustomHTTPHeadersOnRequest(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/_tasks\",\n\t\tParams: url.Values{\n\t\t\t\"pretty\": []string{\"true\"},\n\t\t},\n\t\tHeaders: http.Header{\n\t\t\t\"X-Opaque-Id\": []string{\"123456\"},\n\t\t},\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\tif want, have := \"123456\", res.Header.Get(\"X-Opaque-Id\"); want != have {\n\t\tt.Fatalf(\"want response header X-Opaque-Id=%q, have %q\", want, have)\n\t}\n}\n\nfunc TestPerformRequestWithCustomHTTPHeadersOnClient(t *testing.T) {\n\tclient, err := NewClient(SetHeaders(http.Header{\n\t\t\"Custom-Id\": []string{\"olivere\"},\n\t}))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/_tasks\",\n\t\tParams: url.Values{\n\t\t\t\"pretty\": []string{\"true\"},\n\t\t},\n\t\tHeaders: http.Header{\n\t\t\t\"X-Opaque-Id\": []string{\"123456\"},\n\t\t},\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\t// Request-level headers have preference\n\tif want, have := \"123456\", res.Header.Get(\"X-Opaque-Id\"); want != have {\n\t\tt.Fatalf(\"want X-Opaque-Id=%q, have %q\", want, have)\n\t}\n}\n\nfunc TestPerformRequestSetsDefaultUserAgent(t *testing.T) {\n\tvar req *http.Request\n\th := func(r *http.Request) (*http.Response, error) {\n\t\treq = new(http.Request)\n\t\t*req = *r\n\t\treturn &http.Response{Request: r, StatusCode: http.StatusOK, Body: http.NoBody}, nil\n\t}\n\ttr := &failingTransport{path: \"/\", fail: h}\n\thttpClient := &http.Client{Transport: tr}\n\n\tclient, err := NewClient(SetHttpClient(httpClient), SetSniff(false), SetHealthcheck(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t\tParams: url.Values{\n\t\t\t\"pretty\": []string{\"true\"},\n\t\t},\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\t// Have a default for User-Agent\n\tif want, have := \"elastic/\"+Version+\" (\"+runtime.GOOS+\"-\"+runtime.GOARCH+\")\", req.Header.Get(\"User-Agent\"); want != have {\n\t\tt.Fatalf(\"want User-Agent=%q, have %q\", want, have)\n\t}\n}\n\nfunc TestPerformRequestWithCustomHTTPHeadersPriority(t *testing.T) {\n\tvar req *http.Request\n\th := func(r *http.Request) (*http.Response, error) {\n\t\treq = new(http.Request)\n\t\t*req = *r\n\t\treturn &http.Response{Request: r, StatusCode: http.StatusOK, Body: http.NoBody}, nil\n\t}\n\ttr := &failingTransport{path: \"/\", fail: h}\n\thttpClient := &http.Client{Transport: tr}\n\n\tclient, err := NewClient(SetHttpClient(httpClient), SetHeaders(http.Header{\n\t\t\"Custom-Id\":   []string{\"olivere\"},\n\t\t\"User-Agent\":  []string{\"My user agent\"},\n\t\t\"X-Opaque-Id\": []string{\"sandra\"}, // <- will be overridden by request-level header\n\t}), SetSniff(false), SetHealthcheck(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t\tParams: url.Values{\n\t\t\t\"pretty\": []string{\"true\"},\n\t\t},\n\t\tHeaders: http.Header{\n\t\t\t\"X-Opaque-Id\": []string{\"123456\"}, // <- request-level has preference\n\t\t\t\"X-Somewhat\":  []string{\"somewhat\"},\n\t\t},\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\tif req == nil {\n\t\tt.Fatal(\"expected to record HTTP request\")\n\t}\n\tif want, have := \"123456\", req.Header.Get(\"X-Opaque-Id\"); want != have {\n\t\tt.Fatalf(\"want X-Opaque-Id=%q, have %q\", want, have)\n\t}\n\tif want, have := \"olivere\", req.Header.Get(\"Custom-Id\"); want != have {\n\t\tt.Fatalf(\"want Custom-Id=%q, have %q\", want, have)\n\t}\n\tif want, have := \"My user agent\", req.Header.Get(\"User-Agent\"); want != have {\n\t\tt.Fatalf(\"want User-Agent=%q, have %q\", want, have)\n\t}\n\tif want, have := \"somewhat\", req.Header.Get(\"X-Somewhat\"); want != have {\n\t\tt.Fatalf(\"want X-Somewhat=%q, have %q\", want, have)\n\t}\n}\n\n// -- Compression --\n\n// Notice that the trace log does always print \"Accept-Encoding: gzip\"\n// regardless of whether compression is enabled or not. This is because\n// of the underlying \"httputil.DumpRequestOut\".\n//\n// Use a real HTTP proxy/recorder to convince yourself that\n// \"Accept-Encoding: gzip\" is NOT sent when DisableCompression\n// is set to true.\n//\n// See also:\n// https://groups.google.com/forum/#!topic/golang-nuts/ms8QNCzew8Q\n\nfunc TestPerformRequestWithCompressionEnabled(t *testing.T) {\n\ttestPerformRequestWithCompression(t, &http.Client{\n\t\tTransport: &http.Transport{\n\t\t\tDisableCompression: true,\n\t\t},\n\t})\n}\n\nfunc TestPerformRequestWithCompressionDisabled(t *testing.T) {\n\ttestPerformRequestWithCompression(t, &http.Client{\n\t\tTransport: &http.Transport{\n\t\t\tDisableCompression: false,\n\t\t},\n\t})\n}\n\nfunc testPerformRequestWithCompression(t *testing.T, hc *http.Client) {\n\tclient, err := NewClient(SetHttpClient(hc), SetSniff(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/\",\n\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response to be != nil\")\n\t}\n\n\tret := new(PingResult)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\tt.Fatalf(\"expected no error on decode; got: %v\", err)\n\t}\n\tif ret.ClusterName == \"\" {\n\t\tt.Errorf(\"expected cluster name; got: %q\", ret.ClusterName)\n\t}\n}\n"
  },
  {
    "path": "cluster-test/Makefile",
    "content": ".PHONY: build run-omega-cluster-test\n\ndefault: build\n\nbuild:\n\tgo build cluster-test.go\n\nrun-omega-cluster-test:\n\tgo run -race cluster-test.go \\\n\t\t-nodes=http://192.168.2.65:8200,http://192.168.2.64:8200 \\\n\t\t-n=5 \\\n\t\t-retries=5 \\\n\t\t-sniff=true -sniffer=10s \\\n\t\t-healthcheck=true -healthchecker=5s \\\n\t\t-errorlog=errors.log\n\n"
  },
  {
    "path": "cluster-test/README.md",
    "content": "# Cluster Test\n\nThis directory contains a program you can use to test a cluster.\n\nHere's how:\n\nFirst, install a cluster of Elasticsearch nodes. You can install them on\ndifferent computers, or start several nodes on a single machine.\n\nBuild cluster-test by `go build cluster-test.go` (or build with `make`).\n\nRun `./cluster-test -h` to get a list of flags:\n\n```sh\n$ ./cluster-test -h\nUsage of ./cluster-test:\n  -errorlog=\"\": error log file\n  -healthcheck=true: enable or disable healthchecks\n  -healthchecker=1m0s: healthcheck interval\n  -index=\"twitter\": name of ES index to use\n  -infolog=\"\": info log file\n  -n=5: number of goroutines that run searches\n  -nodes=\"\": comma-separated list of ES URLs (e.g. 'http://192.168.2.10:9200,http://192.168.2.11:9200')\n  -retries=0: number of retries\n  -sniff=true: enable or disable sniffer\n  -sniffer=15m0s: sniffer interval\n  -tracelog=\"\": trace log file\n```\n\nExample:\n\n```sh\n$ ./cluster-test -nodes=http://127.0.0.1:9200,http://127.0.0.1:9201,http://127.0.0.1:9202 -n=5 -index=twitter -retries=5 -sniff=true -sniffer=10s -healthcheck=true -healthchecker=5s -errorlog=error.log\n```\n\nThe above example will create an index and start some search jobs on the\ncluster defined by http://127.0.0.1:9200, http://127.0.0.1:9201,\nand http://127.0.0.1:9202.\n\n* It will create an index called `twitter` on the cluster (`-index=twitter`)\n* It will run 5 search jobs in parallel (`-n=5`).\n* It will retry failed requests 5 times (`-retries=5`).\n* It will sniff the cluster periodically (`-sniff=true`).\n* It will sniff the cluster every 10 seconds (`-sniffer=10s`).\n* It will perform health checks periodically (`-healthcheck=true`).\n* It will perform health checks on the nodes every 5 seconds (`-healthchecker=5s`).\n* It will write an error log file (`-errorlog=error.log`).\n\nIf you want to test Elastic with nodes going up and down, you can use a\nchaos monkey script like this and run it on the nodes of your cluster:\n\n```sh\n#!/bin/bash\nwhile true\ndo\n\techo \"Starting ES node\"\n\telasticsearch -d -Xmx4g -Xms1g -Des.config=elasticsearch.yml -p es.pid\n\tsleep `jot -r 1 10 300` # wait for 10-300s\n\techo \"Stopping ES node\"\n\tkill -TERM `cat es.pid`\n\tsleep `jot -r 1 10 60`  # wait for 10-60s\ndone\n```\n"
  },
  {
    "path": "cluster-test/cluster-test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"os\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\ntype Tweet struct {\n\tUser     string                `json:\"user\"`\n\tMessage  string                `json:\"message\"`\n\tRetweets int                   `json:\"retweets\"`\n\tImage    string                `json:\"image,omitempty\"`\n\tCreated  time.Time             `json:\"created,omitempty\"`\n\tTags     []string              `json:\"tags,omitempty\"`\n\tLocation string                `json:\"location,omitempty\"`\n\tSuggest  *elastic.SuggestField `json:\"suggest_field,omitempty\"`\n}\n\nvar (\n\tnodes         = flag.String(\"nodes\", \"\", \"comma-separated list of ES URLs (e.g. 'http://192.168.2.10:9200,http://192.168.2.11:9200')\")\n\tn             = flag.Int(\"n\", 5, \"number of goroutines that run searches\")\n\tindex         = flag.String(\"index\", \"twitter\", \"name of ES index to use\")\n\terrorlogfile  = flag.String(\"errorlog\", \"\", \"error log file\")\n\tinfologfile   = flag.String(\"infolog\", \"\", \"info log file\")\n\ttracelogfile  = flag.String(\"tracelog\", \"\", \"trace log file\")\n\tretries       = flag.Int(\"retries\", 0, \"number of retries\")\n\tsniff         = flag.Bool(\"sniff\", elastic.DefaultSnifferEnabled, \"enable or disable sniffer\")\n\tsniffer       = flag.Duration(\"sniffer\", elastic.DefaultSnifferInterval, \"sniffer interval\")\n\thealthcheck   = flag.Bool(\"healthcheck\", elastic.DefaultHealthcheckEnabled, \"enable or disable healthchecks\")\n\thealthchecker = flag.Duration(\"healthchecker\", elastic.DefaultHealthcheckInterval, \"healthcheck interval\")\n)\n\nfunc main() {\n\tflag.Parse()\n\n\truntime.GOMAXPROCS(runtime.NumCPU())\n\n\tif *nodes == \"\" {\n\t\tlog.Fatal(\"no nodes specified\")\n\t}\n\turls := strings.SplitN(*nodes, \",\", -1)\n\n\ttestcase, err := NewTestCase(*index, urls)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\ttestcase.SetErrorLogFile(*errorlogfile)\n\ttestcase.SetInfoLogFile(*infologfile)\n\ttestcase.SetTraceLogFile(*tracelogfile)\n\ttestcase.SetMaxRetries(*retries)\n\ttestcase.SetHealthcheck(*healthcheck)\n\ttestcase.SetHealthcheckInterval(*healthchecker)\n\ttestcase.SetSniff(*sniff)\n\ttestcase.SetSnifferInterval(*sniffer)\n\n\tif err := testcase.Run(*n); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tselect {}\n}\n\ntype RunInfo struct {\n\tSuccess bool\n}\n\ntype TestCase struct {\n\tnodes               []string\n\tclient              *elastic.Client\n\truns                int64\n\tfailures            int64\n\trunCh               chan RunInfo\n\tindex               string\n\terrorlogfile        string\n\tinfologfile         string\n\ttracelogfile        string\n\tmaxRetries          int\n\thealthcheck         bool\n\thealthcheckInterval time.Duration\n\tsniff               bool\n\tsnifferInterval     time.Duration\n}\n\nfunc NewTestCase(index string, nodes []string) (*TestCase, error) {\n\tif index == \"\" {\n\t\treturn nil, errors.New(\"no index name specified\")\n\t}\n\n\treturn &TestCase{\n\t\tindex: index,\n\t\tnodes: nodes,\n\t\trunCh: make(chan RunInfo),\n\t}, nil\n}\n\nfunc (t *TestCase) SetIndex(name string) {\n\tt.index = name\n}\n\nfunc (t *TestCase) SetErrorLogFile(name string) {\n\tt.errorlogfile = name\n}\n\nfunc (t *TestCase) SetInfoLogFile(name string) {\n\tt.infologfile = name\n}\n\nfunc (t *TestCase) SetTraceLogFile(name string) {\n\tt.tracelogfile = name\n}\n\nfunc (t *TestCase) SetMaxRetries(n int) {\n\tt.maxRetries = n\n}\n\nfunc (t *TestCase) SetSniff(enabled bool) {\n\tt.sniff = enabled\n}\n\nfunc (t *TestCase) SetSnifferInterval(d time.Duration) {\n\tt.snifferInterval = d\n}\n\nfunc (t *TestCase) SetHealthcheck(enabled bool) {\n\tt.healthcheck = enabled\n}\n\nfunc (t *TestCase) SetHealthcheckInterval(d time.Duration) {\n\tt.healthcheckInterval = d\n}\n\nfunc (t *TestCase) Run(n int) error {\n\tif err := t.setup(); err != nil {\n\t\treturn err\n\t}\n\n\tfor i := 1; i < n; i++ {\n\t\tgo t.search()\n\t}\n\n\tgo t.monitor()\n\n\treturn nil\n}\n\nfunc (t *TestCase) monitor() {\n\tprint := func() {\n\t\tfmt.Printf(\"\\033[32m%5d\\033[0m; \\033[31m%5d\\033[0m: %s%s\\r\", t.runs, t.failures, t.client.String(), \"    \")\n\t}\n\n\tfor {\n\t\tselect {\n\t\tcase run := <-t.runCh:\n\t\t\tatomic.AddInt64(&t.runs, 1)\n\t\t\tif !run.Success {\n\t\t\t\tatomic.AddInt64(&t.failures, 1)\n\t\t\t\tfmt.Println()\n\t\t\t}\n\t\t\tprint()\n\t\tcase <-time.After(5 * time.Second):\n\t\t\t// Print stats after some inactivity\n\t\t\tprint()\n\t\t\tbreak\n\t\t}\n\t}\n}\n\nfunc (t *TestCase) setup() error {\n\tvar options []elastic.ClientOptionFunc\n\n\tif t.errorlogfile != \"\" {\n\t\tf, err := os.OpenFile(t.errorlogfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlogger := log.New(f, \"\", log.Ltime|log.Lmicroseconds|log.Lshortfile)\n\t\toptions = append(options, elastic.SetErrorLog(logger))\n\t}\n\n\tif t.infologfile != \"\" {\n\t\tf, err := os.OpenFile(t.infologfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlogger := log.New(f, \"\", log.LstdFlags)\n\t\toptions = append(options, elastic.SetInfoLog(logger))\n\t}\n\n\t// Trace request and response details like this\n\tif t.tracelogfile != \"\" {\n\t\tf, err := os.OpenFile(t.tracelogfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tlogger := log.New(f, \"\", log.LstdFlags)\n\t\toptions = append(options, elastic.SetTraceLog(logger))\n\t}\n\n\toptions = append(options, elastic.SetURL(t.nodes...))\n\toptions = append(options, elastic.SetMaxRetries(t.maxRetries))\n\toptions = append(options, elastic.SetSniff(t.sniff))\n\toptions = append(options, elastic.SetSnifferInterval(t.snifferInterval))\n\toptions = append(options, elastic.SetHealthcheck(t.healthcheck))\n\toptions = append(options, elastic.SetHealthcheckInterval(t.healthcheckInterval))\n\n\tclient, err := elastic.NewClient(options...)\n\tif err != nil {\n\t\t// Handle error\n\t\treturn err\n\t}\n\tt.client = client\n\n\tctx := context.Background()\n\n\t// Use the IndexExists service to check if a specified index exists.\n\texists, err := t.client.IndexExists(t.index).Do(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif exists {\n\t\tdeleteIndex, err := t.client.DeleteIndex(t.index).Do(ctx)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif !deleteIndex.Acknowledged {\n\t\t\treturn errors.New(\"delete index not acknowledged\")\n\t\t}\n\t}\n\n\t// Create a new index.\n\tcreateIndex, err := t.client.CreateIndex(t.index).Do(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !createIndex.Acknowledged {\n\t\treturn errors.New(\"create index not acknowledged\")\n\t}\n\n\t// Index a tweet (using JSON serialization)\n\ttweet1 := Tweet{User: \"olivere\", Message: \"Take Five\", Retweets: 0}\n\t_, err = t.client.Index().\n\t\tIndex(t.index).\n\t\tType(\"tweet\").\n\t\tId(\"1\").\n\t\tBodyJson(tweet1).\n\t\tDo(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Index a second tweet (by string)\n\ttweet2 := `{\"user\" : \"olivere\", \"message\" : \"It's a Raggy Waltz\"}`\n\t_, err = t.client.Index().\n\t\tIndex(t.index).\n\t\tType(\"tweet\").\n\t\tId(\"2\").\n\t\tBodyString(tweet2).\n\t\tDo(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Flush to make sure the documents got written.\n\t_, err = t.client.Flush().Index(t.index).Do(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (t *TestCase) search() {\n\tctx := context.Background()\n\n\t// Loop forever to check for connection issues\n\tfor {\n\t\t// Get tweet with specified ID\n\t\t_, err := t.client.Get().\n\t\t\tIndex(t.index).\n\t\t\tType(\"tweet\").\n\t\t\tId(\"1\").\n\t\t\tDo(ctx)\n\t\tif err != nil {\n\t\t\t//failf(\"Get failed: %v\", err)\n\t\t\tt.runCh <- RunInfo{Success: false}\n\t\t\tcontinue\n\t\t}\n\t\tif elastic.IsNotFound(err) {\n\t\t\t//log.Printf(\"Document %s not found\\n\", \"1\")\n\t\t\t//fmt.Printf(\"Got document %s in version %d from index %s, type %s\\n\", get1.Id, get1.Version, get1.Index, get1.Type)\n\t\t\tt.runCh <- RunInfo{Success: false}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Search with a term query\n\t\tsearchResult, err := t.client.Search().\n\t\t\tIndex(t.index).                                 // search in index t.index\n\t\t\tQuery(elastic.NewTermQuery(\"user\", \"olivere\")). // specify the query\n\t\t\tSort(\"user\", true).                             // sort by \"user\" field, ascending\n\t\t\tFrom(0).Size(10).                               // take documents 0-9\n\t\t\tPretty(true).                                   // pretty print request and response JSON\n\t\t\tDo(ctx)                                         // execute\n\t\tif err != nil {\n\t\t\t//failf(\"Search failed: %v\\n\", err)\n\t\t\tt.runCh <- RunInfo{Success: false}\n\t\t\tcontinue\n\t\t}\n\n\t\t// searchResult is of type SearchResult and returns hits, suggestions,\n\t\t// and all kinds of other information from Elasticsearch.\n\t\t//fmt.Printf(\"Query took %d milliseconds\\n\", searchResult.TookInMillis)\n\n\t\t// Number of hits\n\t\tif searchResult.Hits.TotalHits.Value > 0 {\n\t\t\t//fmt.Printf(\"Found a total of %d tweets\\n\", searchResult.Hits.TotalHits)\n\n\t\t\t// Iterate through results\n\t\t\tfor _, hit := range searchResult.Hits.Hits {\n\t\t\t\t// hit.Index contains the name of the index\n\n\t\t\t\t// Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).\n\t\t\t\tvar tweet Tweet\n\t\t\t\terr := json.Unmarshal(hit.Source, &tweet)\n\t\t\t\tif err != nil {\n\t\t\t\t\t// Deserialization failed\n\t\t\t\t\t//failf(\"Deserialize failed: %v\\n\", err)\n\t\t\t\t\tt.runCh <- RunInfo{Success: false}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\t// Work with tweet\n\t\t\t\t//fmt.Printf(\"Tweet by %s: %s\\n\", t.User, t.Message)\n\t\t\t}\n\t\t} else {\n\t\t\t// No hits\n\t\t\t//fmt.Print(\"Found no tweets\\n\")\n\t\t}\n\n\t\tt.runCh <- RunInfo{Success: true}\n\n\t\t// Sleep some time\n\t\ttime.Sleep(time.Duration(rand.Intn(500)) * time.Millisecond)\n\t}\n}\n"
  },
  {
    "path": "cluster_health.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// ClusterHealthService allows to get a very simple status on the health of the cluster.\n//\n// See http://www.elastic.co/guide/en/elasticsearch/reference/7.0/cluster-health.html\n// for details.\ntype ClusterHealthService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindices                   []string\n\tlevel                     string\n\tlocal                     *bool\n\tmasterTimeout             string\n\ttimeout                   string\n\twaitForActiveShards       *int\n\twaitForNodes              string\n\twaitForNoRelocatingShards *bool\n\twaitForStatus             string\n}\n\n// NewClusterHealthService creates a new ClusterHealthService.\nfunc NewClusterHealthService(client *Client) *ClusterHealthService {\n\treturn &ClusterHealthService{\n\t\tclient:  client,\n\t\tindices: make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ClusterHealthService) Pretty(pretty bool) *ClusterHealthService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ClusterHealthService) Human(human bool) *ClusterHealthService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ClusterHealthService) ErrorTrace(errorTrace bool) *ClusterHealthService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ClusterHealthService) FilterPath(filterPath ...string) *ClusterHealthService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ClusterHealthService) Header(name string, value string) *ClusterHealthService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ClusterHealthService) Headers(headers http.Header) *ClusterHealthService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index limits the information returned to specific indices.\nfunc (s *ClusterHealthService) Index(indices ...string) *ClusterHealthService {\n\ts.indices = append(s.indices, indices...)\n\treturn s\n}\n\n// Level specifies the level of detail for returned information.\nfunc (s *ClusterHealthService) Level(level string) *ClusterHealthService {\n\ts.level = level\n\treturn s\n}\n\n// Local indicates whether to return local information. If it is true,\n// we do not retrieve the state from master node (default: false).\nfunc (s *ClusterHealthService) Local(local bool) *ClusterHealthService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *ClusterHealthService) MasterTimeout(masterTimeout string) *ClusterHealthService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Timeout specifies an explicit operation timeout.\nfunc (s *ClusterHealthService) Timeout(timeout string) *ClusterHealthService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// WaitForActiveShards can be used to wait until the specified number of shards are active.\nfunc (s *ClusterHealthService) WaitForActiveShards(waitForActiveShards int) *ClusterHealthService {\n\ts.waitForActiveShards = &waitForActiveShards\n\treturn s\n}\n\n// WaitForNodes can be used to wait until the specified number of nodes are available.\n// Example: \"12\" to wait for exact values, \">12\" and \"<12\" for ranges.\nfunc (s *ClusterHealthService) WaitForNodes(waitForNodes string) *ClusterHealthService {\n\ts.waitForNodes = waitForNodes\n\treturn s\n}\n\n// WaitForNoRelocatingShards can be used to wait until all shard relocations are finished.\nfunc (s *ClusterHealthService) WaitForNoRelocatingShards(waitForNoRelocatingShards bool) *ClusterHealthService {\n\ts.waitForNoRelocatingShards = &waitForNoRelocatingShards\n\treturn s\n}\n\n// WaitForStatus can be used to wait until the cluster is in a specific state.\n// Valid values are: green, yellow, or red.\nfunc (s *ClusterHealthService) WaitForStatus(waitForStatus string) *ClusterHealthService {\n\ts.waitForStatus = waitForStatus\n\treturn s\n}\n\n// WaitForGreenStatus will wait for the \"green\" state.\nfunc (s *ClusterHealthService) WaitForGreenStatus() *ClusterHealthService {\n\treturn s.WaitForStatus(\"green\")\n}\n\n// WaitForYellowStatus will wait for the \"yellow\" state.\nfunc (s *ClusterHealthService) WaitForYellowStatus() *ClusterHealthService {\n\treturn s.WaitForStatus(\"yellow\")\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ClusterHealthService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.indices) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_cluster/health/{index}\", map[string]string{\n\t\t\t\"index\": strings.Join(s.indices, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_cluster/health\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.level != \"\" {\n\t\tparams.Set(\"level\", s.level)\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.waitForActiveShards != nil {\n\t\tparams.Set(\"wait_for_active_shards\", fmt.Sprintf(\"%v\", s.waitForActiveShards))\n\t}\n\tif s.waitForNodes != \"\" {\n\t\tparams.Set(\"wait_for_nodes\", s.waitForNodes)\n\t}\n\tif s.waitForNoRelocatingShards != nil {\n\t\tparams.Set(\"wait_for_no_relocating_shards\", fmt.Sprintf(\"%v\", *s.waitForNoRelocatingShards))\n\t}\n\tif s.waitForStatus != \"\" {\n\t\tparams.Set(\"wait_for_status\", s.waitForStatus)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ClusterHealthService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *ClusterHealthService) Do(ctx context.Context) (*ClusterHealthResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(ClusterHealthResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// ClusterHealthResponse is the response of ClusterHealthService.Do.\ntype ClusterHealthResponse struct {\n\tClusterName                    string  `json:\"cluster_name\"`\n\tStatus                         string  `json:\"status\"`\n\tTimedOut                       bool    `json:\"timed_out\"`\n\tNumberOfNodes                  int     `json:\"number_of_nodes\"`\n\tNumberOfDataNodes              int     `json:\"number_of_data_nodes\"`\n\tActivePrimaryShards            int     `json:\"active_primary_shards\"`\n\tActiveShards                   int     `json:\"active_shards\"`\n\tRelocatingShards               int     `json:\"relocating_shards\"`\n\tInitializingShards             int     `json:\"initializing_shards\"`\n\tUnassignedShards               int     `json:\"unassigned_shards\"`\n\tDelayedUnassignedShards        int     `json:\"delayed_unassigned_shards\"`\n\tNumberOfPendingTasks           int     `json:\"number_of_pending_tasks\"`\n\tNumberOfInFlightFetch          int     `json:\"number_of_in_flight_fetch\"`\n\tTaskMaxWaitTimeInQueue         string  `json:\"task_max_waiting_in_queue\"`        // \"0s\"\n\tTaskMaxWaitTimeInQueueInMillis int     `json:\"task_max_waiting_in_queue_millis\"` // 0\n\tActiveShardsPercent            string  `json:\"active_shards_percent\"`            // \"100.0%\"\n\tActiveShardsPercentAsNumber    float64 `json:\"active_shards_percent_as_number\"`  // 100.0\n\n\t// Index name -> index health\n\tIndices map[string]*ClusterIndexHealth `json:\"indices\"`\n}\n\n// ClusterIndexHealth will be returned as part of ClusterHealthResponse.\ntype ClusterIndexHealth struct {\n\tStatus              string `json:\"status\"`\n\tNumberOfShards      int    `json:\"number_of_shards\"`\n\tNumberOfReplicas    int    `json:\"number_of_replicas\"`\n\tActivePrimaryShards int    `json:\"active_primary_shards\"`\n\tActiveShards        int    `json:\"active_shards\"`\n\tRelocatingShards    int    `json:\"relocating_shards\"`\n\tInitializingShards  int    `json:\"initializing_shards\"`\n\tUnassignedShards    int    `json:\"unassigned_shards\"`\n\t// Shards by id, e.g. \"0\" or \"1\"\n\tShards map[string]*ClusterShardHealth `json:\"shards\"`\n}\n\n// ClusterShardHealth will be returned as part of ClusterHealthResponse.\ntype ClusterShardHealth struct {\n\tStatus             string `json:\"status\"`\n\tPrimaryActive      bool   `json:\"primary_active\"`\n\tActiveShards       int    `json:\"active_shards\"`\n\tRelocatingShards   int    `json:\"relocating_shards\"`\n\tInitializingShards int    `json:\"initializing_shards\"`\n\tUnassignedShards   int    `json:\"unassigned_shards\"`\n}\n"
  },
  {
    "path": "cluster_health_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"net/url\"\n\t\"testing\"\n)\n\nfunc TestClusterHealth(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// Get cluster health\n\tres, err := client.ClusterHealth().Index(testIndexName).Level(\"shards\").Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected res to be != nil; got: %v\", res)\n\t}\n\tif res.Status != \"green\" && res.Status != \"red\" && res.Status != \"yellow\" {\n\t\tt.Fatalf(\"expected status \\\"green\\\", \\\"red\\\", or \\\"yellow\\\"; got: %q\", res.Status)\n\t}\n}\n\nfunc TestClusterHealthURLs(t *testing.T) {\n\ttests := []struct {\n\t\tService        *ClusterHealthService\n\t\tExpectedPath   string\n\t\tExpectedParams url.Values\n\t}{\n\t\t{\n\t\t\tService: &ClusterHealthService{\n\t\t\t\tindices: []string{},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/health\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterHealthService{\n\t\t\t\tindices: []string{\"twitter\"},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/health/twitter\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterHealthService{\n\t\t\t\tindices: []string{\"twitter\", \"gplus\"},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/health/twitter%2Cgplus\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterHealthService{\n\t\t\t\tindices:       []string{\"twitter\"},\n\t\t\t\twaitForStatus: \"yellow\",\n\t\t\t},\n\t\t\tExpectedPath:   \"/_cluster/health/twitter\",\n\t\t\tExpectedParams: url.Values{\"wait_for_status\": []string{\"yellow\"}},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tgotPath, gotParams, err := test.Service.buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t\t}\n\t\tif gotPath != test.ExpectedPath {\n\t\t\tt.Errorf(\"expected URL path = %q; got: %q\", test.ExpectedPath, gotPath)\n\t\t}\n\t\tif gotParams.Encode() != test.ExpectedParams.Encode() {\n\t\t\tt.Errorf(\"expected URL params = %v; got: %v\", test.ExpectedParams, gotParams)\n\t\t}\n\t}\n}\n\nfunc TestClusterHealthWaitForStatus(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Ensure preconditions are met: A green cluster.\n\thealth, err := client.ClusterHealth().Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got, want := health.Status, \"green\"; got != want {\n\t\tt.Skipf(\"precondition failed: expected cluster to be %q, not %q\", want, got)\n\t}\n\n\t// Cluster health on an index that does not exist should never get to yellow\n\thealth, err = client.ClusterHealth().Index(\"no-such-index\").WaitForStatus(\"yellow\").Timeout(\"1s\").Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected timeout error; got: %v\", err)\n\t}\n\tif !IsTimeout(err) {\n\t\tt.Fatalf(\"expected timeout error; got: %v\", err)\n\t}\n\tif health != nil {\n\t\tt.Fatalf(\"expected no response; got: %v\", health)\n\t}\n\n\t// Cluster wide health\n\thealth, err = client.ClusterHealth().WaitForGreenStatus().Timeout(\"10s\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif health.TimedOut != false {\n\t\tt.Fatalf(\"expected no timeout; got: %v \"+\n\t\t\t\"(does your local cluster contain unassigned shards?)\", health.TimedOut)\n\t}\n\tif health.Status != \"green\" {\n\t\tt.Fatalf(\"expected health = %q; got: %q\", \"green\", health.Status)\n\t}\n\n\t// Cluster wide health via shortcut on client\n\terr = client.WaitForGreenStatus(\"10s\")\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n}\n"
  },
  {
    "path": "cluster_reroute.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// ClusterRerouteService allows for manual changes to the allocation of\n// individual shards in the cluster. For example, a shard can be moved from\n// one node to another explicitly, an allocation can be cancelled, and\n// an unassigned shard can be explicitly allocated to a specific node.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cluster-reroute.html\n// for details.\ntype ClusterRerouteService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tmetrics       []string\n\tdryRun        *bool\n\texplain       *bool\n\tretryFailed   *bool\n\tmasterTimeout string\n\ttimeout       string\n\tcommands      []AllocationCommand\n\tbody          interface{}\n}\n\n// NewClusterRerouteService creates a new ClusterRerouteService.\nfunc NewClusterRerouteService(client *Client) *ClusterRerouteService {\n\treturn &ClusterRerouteService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ClusterRerouteService) Pretty(pretty bool) *ClusterRerouteService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ClusterRerouteService) Human(human bool) *ClusterRerouteService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ClusterRerouteService) ErrorTrace(errorTrace bool) *ClusterRerouteService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ClusterRerouteService) FilterPath(filterPath ...string) *ClusterRerouteService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ClusterRerouteService) Header(name string, value string) *ClusterRerouteService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ClusterRerouteService) Headers(headers http.Header) *ClusterRerouteService {\n\ts.headers = headers\n\treturn s\n}\n\n// Metric limits the information returned to the specified metric.\n// It can be one of: \"_all\", \"blocks\", \"metadata\", \"nodes\", \"routing_table\", \"master_node\", \"version\".\n// Defaults to all but metadata.\nfunc (s *ClusterRerouteService) Metric(metrics ...string) *ClusterRerouteService {\n\ts.metrics = append(s.metrics, metrics...)\n\treturn s\n}\n\n// DryRun indicates whether to simulate the operation only and return the\n// resulting state.\nfunc (s *ClusterRerouteService) DryRun(dryRun bool) *ClusterRerouteService {\n\ts.dryRun = &dryRun\n\treturn s\n}\n\n// Explain, when set to true, returns an explanation of why the commands\n// can or cannot be executed.\nfunc (s *ClusterRerouteService) Explain(explain bool) *ClusterRerouteService {\n\ts.explain = &explain\n\treturn s\n}\n\n// RetryFailed indicates whether to retry allocation of shards that are blocked\n// due to too many subsequent allocation failures.\nfunc (s *ClusterRerouteService) RetryFailed(retryFailed bool) *ClusterRerouteService {\n\ts.retryFailed = &retryFailed\n\treturn s\n}\n\n// MasterTimeout specifies an explicit timeout for connection to master.\nfunc (s *ClusterRerouteService) MasterTimeout(masterTimeout string) *ClusterRerouteService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Timeout specifies an explicit operationtimeout.\nfunc (s *ClusterRerouteService) Timeout(timeout string) *ClusterRerouteService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// Add adds one or more commands to be executed.\nfunc (s *ClusterRerouteService) Add(commands ...AllocationCommand) *ClusterRerouteService {\n\ts.commands = append(s.commands, commands...)\n\treturn s\n}\n\n// Body specifies the body to be sent.\n// If you specify Body, the commands passed via Add are ignored.\n// In other words: Body takes precedence over Add.\nfunc (s *ClusterRerouteService) Body(body interface{}) *ClusterRerouteService {\n\ts.body = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ClusterRerouteService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath := \"/_cluster/reroute\"\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.dryRun; v != nil {\n\t\tparams.Set(\"dry_run\", fmt.Sprint(*v))\n\t}\n\tif v := s.explain; v != nil {\n\t\tparams.Set(\"explain\", fmt.Sprint(*v))\n\t}\n\tif v := s.retryFailed; v != nil {\n\t\tparams.Set(\"retry_failed\", fmt.Sprint(*v))\n\t}\n\tif len(s.metrics) > 0 {\n\t\tparams.Set(\"metric\", strings.Join(s.metrics, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ClusterRerouteService) Validate() error {\n\tif s.body == nil && len(s.commands) == 0 {\n\t\treturn errors.New(\"missing allocate commands or raw body\")\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *ClusterRerouteService) Do(ctx context.Context) (*ClusterRerouteResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.body != nil {\n\t\tbody = s.body\n\t} else {\n\t\tcommands := make([]interface{}, len(s.commands))\n\t\tfor i, cmd := range s.commands {\n\t\t\tsrc, err := cmd.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tcommands[i] = map[string]interface{}{\n\t\t\t\tcmd.Name(): src,\n\t\t\t}\n\t\t}\n\t\tquery := make(map[string]interface{})\n\t\tquery[\"commands\"] = commands\n\t\tbody = query\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(ClusterRerouteResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// ClusterRerouteResponse is the response of ClusterRerouteService.Do.\ntype ClusterRerouteResponse struct {\n\tState        *ClusterStateResponse `json:\"state\"`\n\tExplanations []RerouteExplanation  `json:\"explanations,omitempty\"`\n}\n\n// RerouteExplanation is returned in ClusterRerouteResponse if\n// the \"explain\" parameter is set to \"true\".\ntype RerouteExplanation struct {\n\tCommand    string                 `json:\"command\"`\n\tParameters map[string]interface{} `json:\"parameters\"`\n\tDecisions  []RerouteDecision      `json:\"decisions\"`\n}\n\n// RerouteDecision is a decision the decider made while rerouting.\ntype RerouteDecision interface{}\n\n// -- Allocation commands --\n\n// AllocationCommand is a command to be executed in a call\n// to Cluster Reroute API.\ntype AllocationCommand interface {\n\tName() string\n\tSource() (interface{}, error)\n}\n\nvar _ AllocationCommand = (*MoveAllocationCommand)(nil)\n\n// MoveAllocationCommand moves a shard from a specific node to\n// another node.\ntype MoveAllocationCommand struct {\n\tindex    string\n\tshardId  int\n\tfromNode string\n\ttoNode   string\n}\n\n// NewMoveAllocationCommand creates a new MoveAllocationCommand.\nfunc NewMoveAllocationCommand(index string, shardId int, fromNode, toNode string) *MoveAllocationCommand {\n\treturn &MoveAllocationCommand{\n\t\tindex:    index,\n\t\tshardId:  shardId,\n\t\tfromNode: fromNode,\n\t\ttoNode:   toNode,\n\t}\n}\n\n// Name of the command in a request to the Cluster Reroute API.\nfunc (cmd *MoveAllocationCommand) Name() string { return \"move\" }\n\n// Source generates the (inner) JSON to be used when serializing the command.\nfunc (cmd *MoveAllocationCommand) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tsource[\"index\"] = cmd.index\n\tsource[\"shard\"] = cmd.shardId\n\tsource[\"from_node\"] = cmd.fromNode\n\tsource[\"to_node\"] = cmd.toNode\n\treturn source, nil\n}\n\nvar _ AllocationCommand = (*CancelAllocationCommand)(nil)\n\n// CancelAllocationCommand cancels relocation, or recovery of a given shard on a node.\ntype CancelAllocationCommand struct {\n\tindex        string\n\tshardId      int\n\tnode         string\n\tallowPrimary bool\n}\n\n// NewCancelAllocationCommand creates a new CancelAllocationCommand.\nfunc NewCancelAllocationCommand(index string, shardId int, node string, allowPrimary bool) *CancelAllocationCommand {\n\treturn &CancelAllocationCommand{\n\t\tindex:        index,\n\t\tshardId:      shardId,\n\t\tnode:         node,\n\t\tallowPrimary: allowPrimary,\n\t}\n}\n\n// Name of the command in a request to the Cluster Reroute API.\nfunc (cmd *CancelAllocationCommand) Name() string { return \"cancel\" }\n\n// Source generates the (inner) JSON to be used when serializing the command.\nfunc (cmd *CancelAllocationCommand) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tsource[\"index\"] = cmd.index\n\tsource[\"shard\"] = cmd.shardId\n\tsource[\"node\"] = cmd.node\n\tsource[\"allow_primary\"] = cmd.allowPrimary\n\treturn source, nil\n}\n\nvar _ AllocationCommand = (*AllocateStalePrimaryAllocationCommand)(nil)\n\n// AllocateStalePrimaryAllocationCommand allocates an unassigned stale\n// primary shard to a specific node. Use with extreme care as this will\n// result in data loss. Allocation deciders are ignored.\ntype AllocateStalePrimaryAllocationCommand struct {\n\tindex          string\n\tshardId        int\n\tnode           string\n\tacceptDataLoss bool\n}\n\n// NewAllocateStalePrimaryAllocationCommand creates a new\n// AllocateStalePrimaryAllocationCommand.\nfunc NewAllocateStalePrimaryAllocationCommand(index string, shardId int, node string, acceptDataLoss bool) *AllocateStalePrimaryAllocationCommand {\n\treturn &AllocateStalePrimaryAllocationCommand{\n\t\tindex:          index,\n\t\tshardId:        shardId,\n\t\tnode:           node,\n\t\tacceptDataLoss: acceptDataLoss,\n\t}\n}\n\n// Name of the command in a request to the Cluster Reroute API.\nfunc (cmd *AllocateStalePrimaryAllocationCommand) Name() string { return \"allocate_stale_primary\" }\n\n// Source generates the (inner) JSON to be used when serializing the command.\nfunc (cmd *AllocateStalePrimaryAllocationCommand) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tsource[\"index\"] = cmd.index\n\tsource[\"shard\"] = cmd.shardId\n\tsource[\"node\"] = cmd.node\n\tsource[\"accept_data_loss\"] = cmd.acceptDataLoss\n\treturn source, nil\n}\n\nvar _ AllocationCommand = (*AllocateReplicaAllocationCommand)(nil)\n\n// AllocateReplicaAllocationCommand allocates an unassigned replica shard\n// to a specific node. Checks if allocation deciders allow allocation.\ntype AllocateReplicaAllocationCommand struct {\n\tindex   string\n\tshardId int\n\tnode    string\n}\n\n// NewAllocateReplicaAllocationCommand creates a new\n// AllocateReplicaAllocationCommand.\nfunc NewAllocateReplicaAllocationCommand(index string, shardId int, node string) *AllocateReplicaAllocationCommand {\n\treturn &AllocateReplicaAllocationCommand{\n\t\tindex:   index,\n\t\tshardId: shardId,\n\t\tnode:    node,\n\t}\n}\n\n// Name of the command in a request to the Cluster Reroute API.\nfunc (cmd *AllocateReplicaAllocationCommand) Name() string { return \"allocate_replica\" }\n\n// Source generates the (inner) JSON to be used when serializing the command.\nfunc (cmd *AllocateReplicaAllocationCommand) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tsource[\"index\"] = cmd.index\n\tsource[\"shard\"] = cmd.shardId\n\tsource[\"node\"] = cmd.node\n\treturn source, nil\n}\n\n// AllocateEmptyPrimaryAllocationCommand allocates an unassigned empty\n// primary shard to a specific node. Use with extreme care as this will\n// result in data loss. Allocation deciders are ignored.\ntype AllocateEmptyPrimaryAllocationCommand struct {\n\tindex          string\n\tshardId        int\n\tnode           string\n\tacceptDataLoss bool\n}\n\n// NewAllocateEmptyPrimaryAllocationCommand creates a new\n// AllocateEmptyPrimaryAllocationCommand.\nfunc NewAllocateEmptyPrimaryAllocationCommand(index string, shardId int, node string, acceptDataLoss bool) *AllocateEmptyPrimaryAllocationCommand {\n\treturn &AllocateEmptyPrimaryAllocationCommand{\n\t\tindex:          index,\n\t\tshardId:        shardId,\n\t\tnode:           node,\n\t\tacceptDataLoss: acceptDataLoss,\n\t}\n}\n\n// Name of the command in a request to the Cluster Reroute API.\nfunc (cmd *AllocateEmptyPrimaryAllocationCommand) Name() string { return \"allocate_empty_primary\" }\n\n// Source generates the (inner) JSON to be used when serializing the command.\nfunc (cmd *AllocateEmptyPrimaryAllocationCommand) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tsource[\"index\"] = cmd.index\n\tsource[\"shard\"] = cmd.shardId\n\tsource[\"node\"] = cmd.node\n\tsource[\"accept_data_loss\"] = cmd.acceptDataLoss\n\treturn source, nil\n}\n"
  },
  {
    "path": "cluster_reroute_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"net/url\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestClusterRerouteURLs(t *testing.T) {\n\ttrueFlag := true\n\ttruePtr := &trueFlag\n\n\ttests := []struct {\n\t\tService        *ClusterRerouteService\n\t\tExpectedPath   string\n\t\tExpectedParams url.Values\n\t}{\n\t\t{\n\t\t\tService:      &ClusterRerouteService{},\n\t\t\tExpectedPath: \"/_cluster/reroute\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterRerouteService{\n\t\t\t\tdryRun:  truePtr,\n\t\t\t\tmetrics: []string{\"blocks\", \"nodes\"},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/reroute\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"dry_run\": []string{\"true\"},\n\t\t\t\t\"metric\":  []string{\"blocks,nodes\"},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tgotPath, gotParams, err := tt.Service.buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t\t}\n\t\tif gotPath != tt.ExpectedPath {\n\t\t\tt.Errorf(\"expected URL path = %q; got: %q\", tt.ExpectedPath, gotPath)\n\t\t}\n\t\tif gotParams.Encode() != tt.ExpectedParams.Encode() {\n\t\t\tt.Errorf(\"expected URL params = %v; got: %v\", tt.ExpectedParams, gotParams)\n\t\t}\n\t}\n}\n\nfunc TestClusterReroute(t *testing.T) {\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tt.Run(\"Commands\", func(t *testing.T) {\n\t\ttestClusterRerouteWithCommands(client, t)\n\t})\n\tt.Run(\"NoBody\", func(t *testing.T) {\n\t\ttestClusterRerouteWithoutBody(client, t)\n\t})\n}\n\nfunc testClusterRerouteWithCommands(client *Client, t *testing.T) {\n\t// Get cluster nodes\n\tvar nodes []string\n\t{\n\t\tres, err := client.ClusterState().Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tfor node := range res.Nodes {\n\t\t\tnodes = append(nodes, node)\n\t\t}\n\t\tif len(nodes) == 0 {\n\t\t\tt.Fatal(\"expected at least one node in cluster\")\n\t\t}\n\t}\n\n\t// Perform a nop cluster reroute\n\tres, err := client.ClusterReroute().\n\t\tDryRun(true).\n\t\tAdd(\n\t\t\tNewMoveAllocationCommand(testIndexName, 0, nodes[0], nodes[0]),\n\t\t\tNewCancelAllocationCommand(testIndexName, 0, nodes[0], true),\n\t\t).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\t// Expect an error here: We just test if it's of a specific kind\n\tif err == nil {\n\t\tt.Fatal(\"expected an error, got nil\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected res to be != nil; got: %v\", res)\n\t}\n\te, ok := err.(*Error)\n\tif !ok {\n\t\tt.Fatalf(\"expected an error of type *elastic.Error, got %T\", err)\n\t}\n\tif want, have := 400, e.Status; want != have {\n\t\tt.Fatalf(\"expected Status=%d, have %d\", want, have)\n\t}\n}\n\nfunc testClusterRerouteWithoutBody(client *Client, t *testing.T) {\n\t// Perform a nop cluster reroute\n\tres, err := client.ClusterReroute().\n\t\tDryRun(true).\n\t\tPretty(true).\n\t\tRetryFailed(true).\n\t\tMasterTimeout(\"10s\").\n\t\tDo(context.Background())\n\t// Expect an error here: We just test if it's of a specific kind\n\tif err == nil {\n\t\tt.Fatal(\"expected an error, got nil\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected res to be != nil; got: %v\", res)\n\t}\n\tif !strings.Contains(err.Error(), \"missing allocate commands or raw body\") {\n\t\tt.Fatalf(\"expected Error~=%s, have %s\", \"missing allocate commands or raw body\", err.Error())\n\t}\n}\n"
  },
  {
    "path": "cluster_state.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// ClusterStateService allows to get a comprehensive state information of the whole cluster.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cluster-state.html\n// for details.\ntype ClusterStateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindices           []string\n\tmetrics           []string\n\tallowNoIndices    *bool\n\texpandWildcards   string\n\tflatSettings      *bool\n\tignoreUnavailable *bool\n\tlocal             *bool\n\tmasterTimeout     string\n}\n\n// NewClusterStateService creates a new ClusterStateService.\nfunc NewClusterStateService(client *Client) *ClusterStateService {\n\treturn &ClusterStateService{\n\t\tclient:  client,\n\t\tindices: make([]string, 0),\n\t\tmetrics: make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ClusterStateService) Pretty(pretty bool) *ClusterStateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ClusterStateService) Human(human bool) *ClusterStateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ClusterStateService) ErrorTrace(errorTrace bool) *ClusterStateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ClusterStateService) FilterPath(filterPath ...string) *ClusterStateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ClusterStateService) Header(name string, value string) *ClusterStateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ClusterStateService) Headers(headers http.Header) *ClusterStateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names. Use _all or an empty string to\n// perform the operation on all indices.\nfunc (s *ClusterStateService) Index(indices ...string) *ClusterStateService {\n\ts.indices = append(s.indices, indices...)\n\treturn s\n}\n\n// Metric limits the information returned to the specified metric.\n// It can be one of: version, master_node, nodes, routing_table, metadata,\n// blocks, or customs.\nfunc (s *ClusterStateService) Metric(metrics ...string) *ClusterStateService {\n\ts.metrics = append(s.metrics, metrics...)\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices.\n// (This includes `_all` string or when no indices have been specified).\nfunc (s *ClusterStateService) AllowNoIndices(allowNoIndices bool) *ClusterStateService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both..\nfunc (s *ClusterStateService) ExpandWildcards(expandWildcards string) *ClusterStateService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// FlatSettings, when set, returns settings in flat format (default: false).\nfunc (s *ClusterStateService) FlatSettings(flatSettings bool) *ClusterStateService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *ClusterStateService) IgnoreUnavailable(ignoreUnavailable bool) *ClusterStateService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// Local indicates whether to return local information. When set, it does not\n// retrieve the state from master node (default: false).\nfunc (s *ClusterStateService) Local(local bool) *ClusterStateService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout specifies timeout for connection to master.\nfunc (s *ClusterStateService) MasterTimeout(masterTimeout string) *ClusterStateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ClusterStateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tmetrics := strings.Join(s.metrics, \",\")\n\tif metrics == \"\" {\n\t\tmetrics = \"_all\"\n\t}\n\tindices := strings.Join(s.indices, \",\")\n\tif indices == \"\" {\n\t\tindices = \"_all\"\n\t}\n\tpath, err := uritemplates.Expand(\"/_cluster/state/{metrics}/{indices}\", map[string]string{\n\t\t\"metrics\": metrics,\n\t\t\"indices\": indices,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprintf(\"%v\", *s.flatSettings))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ClusterStateService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *ClusterStateService) Do(ctx context.Context) (*ClusterStateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(ClusterStateResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// ClusterStateResponse is the response of ClusterStateService.Do.\ntype ClusterStateResponse struct {\n\tClusterName       string                    `json:\"cluster_name\"`\n\tClusterUUID       string                    `json:\"cluster_uuid\"`\n\tVersion           int64                     `json:\"version\"`\n\tStateUUID         string                    `json:\"state_uuid\"`\n\tMasterNode        string                    `json:\"master_node\"`\n\tBlocks            map[string]*clusterBlocks `json:\"blocks\"`\n\tNodes             map[string]*discoveryNode `json:\"nodes\"`\n\tMetadata          *clusterStateMetadata     `json:\"metadata\"`\n\tRoutingTable      *clusterStateRoutingTable `json:\"routing_table\"`\n\tRoutingNodes      *clusterStateRoutingNode  `json:\"routing_nodes\"`\n\tSnapshots         map[string]interface{}    `json:\"snapshots\"`\n\tSnapshotDeletions map[string]interface{}    `json:\"snapshot_deletions\"`\n\tCustoms           map[string]interface{}    `json:\"customs\"`\n}\n\ntype clusterBlocks struct {\n\tGlobal  map[string]*clusterBlock `json:\"global\"`  // id -> cluster block\n\tIndices map[string]*clusterBlock `json:\"indices\"` // index name -> cluster block\n}\n\ntype clusterBlock struct {\n\tDescription             string   `json:\"description\"`\n\tRetryable               bool     `json:\"retryable\"`\n\tDisableStatePersistence bool     `json:\"disable_state_persistence\"`\n\tLevels                  []string `json:\"levels\"`\n}\n\ntype clusterStateMetadata struct {\n\tClusterUUID          string                            `json:\"cluster_uuid\"`\n\tClusterUUIDCommitted bool                              `json:\"cluster_uuid_committed\"`\n\tClusterCoordination  *clusterCoordinationMetaData      `json:\"cluster_coordination\"`\n\tTemplates            map[string]*indexTemplateMetaData `json:\"templates\"` // template name -> index template metadata\n\tIndices              map[string]*indexMetaData         `json:\"indices\"`   // index name _> meta data\n\tRoutingTable         struct {\n\t\tIndices map[string]*indexRoutingTable `json:\"indices\"` // index name -> routing table\n\t} `json:\"routing_table\"`\n\tRoutingNodes struct {\n\t\tUnassigned []*shardRouting `json:\"unassigned\"`\n\t\tNodes      []*shardRouting `json:\"nodes\"`\n\t} `json:\"routing_nodes\"`\n\tDataStream        map[string]interface{} `json:\"data_stream,omitempty\"`\n\tCustoms           map[string]interface{} `json:\"customs\"`\n\tIngest            map[string]interface{} `json:\"ingest\"`\n\tStoredScripts     map[string]interface{} `json:\"stored_scripts\"`\n\tIndexGraveyard    map[string]interface{} `json:\"index-graveyard\"`\n\tIndexLifecycle    map[string]interface{} `json:\"index_lifecycle\"`\n\tRepositories      map[string]interface{} `json:\"repositories\"`\n\tIndexTemplate     map[string]interface{} `json:\"index_template\"`\n\tPersistentTasks   map[string]interface{} `json:\"persistent_tasks\"`\n\tComponentTemplate map[string]interface{} `json:\"component_template\"`\n}\n\ntype clusterCoordinationMetaData struct {\n\tTerm                   int64         `json:\"term\"`\n\tLastCommittedConfig    interface{}   `json:\"last_committed_config,omitempty\"`\n\tLastAcceptedConfig     interface{}   `json:\"last_accepted_config,omitempty\"`\n\tVotingConfigExclusions []interface{} `json:\"voting_config_exclusions,omitempty\"`\n}\n\ntype discoveryNode struct {\n\tName             string                 `json:\"name\"`              // server name, e.g. \"es1\"\n\tEphemeralID      string                 `json:\"ephemeral_id\"`      // e.g. \"paHSLpn6QyuVy_n-GM1JAQ\"\n\tTransportAddress string                 `json:\"transport_address\"` // e.g. inet[/1.2.3.4:9300]\n\tAttributes       map[string]interface{} `json:\"attributes\"`        // e.g. { \"data\": true, \"master\": true }\n\tRoles            []string               `json:\"roles,omitempty\"`   // e.g. [\"data\",\"data_cold\",\"master\",...]\n}\n\ntype clusterStateRoutingTable struct {\n\tIndices map[string]interface{} `json:\"indices\"`\n}\n\ntype clusterStateRoutingNode struct {\n\tUnassigned []*shardRouting `json:\"unassigned\"`\n\t// Node Id -> shardRouting\n\tNodes map[string][]*shardRouting `json:\"nodes\"`\n}\n\ntype indexTemplateMetaData struct {\n\tIndexPatterns []string               `json:\"index_patterns\"` // e.g. [\"store-*\"]\n\tOrder         int                    `json:\"order\"`\n\tVersion       int                    `json:\"version\"`\n\tSettings      map[string]interface{} `json:\"settings\"` // index settings\n\tMappings      map[string]interface{} `json:\"mappings\"` // type name -> mapping\n\tAliases       map[string]interface{} `json:\"aliases\"`\n}\n\ntype indexMetaData struct {\n\tState             string                 `json:\"state\"`\n\tSettings          map[string]interface{} `json:\"settings\"`\n\tMappings          map[string]interface{} `json:\"mappings\"`\n\tAliases           []string               `json:\"aliases\"` // e.g. [ \"alias1\", \"alias2\" ]\n\tPrimaryTerms      map[string]interface{} `json:\"primary_terms\"`\n\tInSyncAllocations map[string]interface{} `json:\"in_sync_allocations\"`\n\tVersion           int                    `json:\"version\"`\n\tMappingVersion    int                    `json:\"mapping_version\"`\n\tSettingsVersion   int                    `json:\"settings_version\"`\n\tAliasesVersion    int                    `json:\"aliases_version\"`\n\tRoutingNumShards  int                    `json:\"routing_num_shards\"`\n\tRolloverInfo      interface{}            `json:\"rollover_info,omitempty\"`\n\tSystem            interface{}            `json:\"system,omitempty\"`\n\tTimestampRange    interface{}            `json:\"timestamp_range,omitempty\"`\n\tILM               map[string]interface{} `json:\"ilm,omitempty\"`\n}\n\ntype indexRoutingTable struct {\n\tShards map[string]*shardRouting `json:\"shards\"`\n}\n\ntype shardRouting struct {\n\tState          string          `json:\"state\"`\n\tPrimary        bool            `json:\"primary\"`\n\tNode           string          `json:\"node\"`\n\tRelocatingNode string          `json:\"relocating_node\"`\n\tShard          int             `json:\"shard\"`\n\tIndex          string          `json:\"index\"`\n\tVersion        int64           `json:\"version\"`\n\tRestoreSource  *RestoreSource  `json:\"restore_source\"`\n\tAllocationId   *allocationId   `json:\"allocation_id\"`\n\tUnassignedInfo *unassignedInfo `json:\"unassigned_info\"`\n}\n\ntype RestoreSource struct {\n\tRepository string `json:\"repository\"`\n\tSnapshot   string `json:\"snapshot\"`\n\tVersion    string `json:\"version\"`\n\tIndex      string `json:\"index\"`\n}\n\ntype allocationId struct {\n\tId           string `json:\"id\"`\n\tRelocationId string `json:\"relocation_id\"`\n}\n\ntype unassignedInfo struct {\n\tReason  string `json:\"reason\"`\n\tAt      string `json:\"at\"`\n\tDetails string `json:\"details\"`\n}\n"
  },
  {
    "path": "cluster_state_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"net/url\"\n\t\"testing\"\n)\n\nfunc TestClusterState(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// Get cluster state\n\tres, err := client.ClusterState().Index(\"_all\").Metric(\"_all\").Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected res to be != nil; got: %v\", res)\n\t}\n\tif res.ClusterName == \"\" {\n\t\tt.Fatalf(\"expected a cluster name; got: %q\", res.ClusterName)\n\t}\n}\n\nfunc TestClusterStateURLs(t *testing.T) {\n\ttests := []struct {\n\t\tService        *ClusterStateService\n\t\tExpectedPath   string\n\t\tExpectedParams url.Values\n\t}{\n\t\t{\n\t\t\tService: &ClusterStateService{\n\t\t\t\tindices: []string{},\n\t\t\t\tmetrics: []string{},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/state/_all/_all\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterStateService{\n\t\t\t\tindices: []string{\"twitter\"},\n\t\t\t\tmetrics: []string{},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/state/_all/twitter\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterStateService{\n\t\t\t\tindices: []string{\"twitter\", \"gplus\"},\n\t\t\t\tmetrics: []string{},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/state/_all/twitter%2Cgplus\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterStateService{\n\t\t\t\tindices: []string{},\n\t\t\t\tmetrics: []string{\"nodes\"},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/state/nodes/_all\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterStateService{\n\t\t\t\tindices: []string{\"twitter\"},\n\t\t\t\tmetrics: []string{\"nodes\"},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/state/nodes/twitter\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterStateService{\n\t\t\t\tindices:       []string{\"twitter\"},\n\t\t\t\tmetrics:       []string{\"nodes\"},\n\t\t\t\tmasterTimeout: \"1s\",\n\t\t\t},\n\t\t\tExpectedPath:   \"/_cluster/state/nodes/twitter\",\n\t\t\tExpectedParams: url.Values{\"master_timeout\": []string{\"1s\"}},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tgotPath, gotParams, err := test.Service.buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t\t}\n\t\tif gotPath != test.ExpectedPath {\n\t\t\tt.Errorf(\"expected URL path = %q; got: %q\", test.ExpectedPath, gotPath)\n\t\t}\n\t\tif gotParams.Encode() != test.ExpectedParams.Encode() {\n\t\t\tt.Errorf(\"expected URL params = %v; got: %v\", test.ExpectedParams, gotParams)\n\t\t}\n\t}\n}\n\nfunc TestClusterStateGet(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tstate, err := client.ClusterState().Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := \"elasticsearch\", state.ClusterName; want != have {\n\t\tt.Fatalf(\"ClusterName: want %q, have %q\", want, have)\n\t}\n}\n"
  },
  {
    "path": "cluster_stats.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// ClusterStatsService is documented at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cluster-stats.html.\ntype ClusterStatsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tnodeId       []string\n\tflatSettings *bool\n}\n\n// NewClusterStatsService creates a new ClusterStatsService.\nfunc NewClusterStatsService(client *Client) *ClusterStatsService {\n\treturn &ClusterStatsService{\n\t\tclient: client,\n\t\tnodeId: make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ClusterStatsService) Pretty(pretty bool) *ClusterStatsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ClusterStatsService) Human(human bool) *ClusterStatsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ClusterStatsService) ErrorTrace(errorTrace bool) *ClusterStatsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ClusterStatsService) FilterPath(filterPath ...string) *ClusterStatsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ClusterStatsService) Header(name string, value string) *ClusterStatsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ClusterStatsService) Headers(headers http.Header) *ClusterStatsService {\n\ts.headers = headers\n\treturn s\n}\n\n// NodeId is documented as: A comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node you're connecting to, leave empty to get information from all nodes.\nfunc (s *ClusterStatsService) NodeId(nodeId []string) *ClusterStatsService {\n\ts.nodeId = nodeId\n\treturn s\n}\n\n// FlatSettings is documented as: Return settings in flat format (default: false).\nfunc (s *ClusterStatsService) FlatSettings(flatSettings bool) *ClusterStatsService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ClusterStatsService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\n\tif len(s.nodeId) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_cluster/stats/nodes/{node_id}\", map[string]string{\n\t\t\t\"node_id\": strings.Join(s.nodeId, \",\"),\n\t\t})\n\t\tif err != nil {\n\t\t\treturn \"\", url.Values{}, err\n\t\t}\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/_cluster/stats\", map[string]string{})\n\t\tif err != nil {\n\t\t\treturn \"\", url.Values{}, err\n\t\t}\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprintf(\"%v\", *s.flatSettings))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ClusterStatsService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *ClusterStatsService) Do(ctx context.Context) (*ClusterStatsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(ClusterStatsResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// ClusterStatsResponse is the response of ClusterStatsService.Do.\ntype ClusterStatsResponse struct {\n\tNodesStats  *ClusterStatsNodesResponse `json:\"_nodes,omitempty\"`\n\tTimestamp   int64                      `json:\"timestamp\"`\n\tClusterName string                     `json:\"cluster_name\"`\n\tClusterUUID string                     `json:\"cluster_uuid\"`\n\tStatus      string                     `json:\"status,omitempty\"` // e.g. green\n\tIndices     *ClusterStatsIndices       `json:\"indices\"`\n\tNodes       *ClusterStatsNodes         `json:\"nodes\"`\n}\n\ntype ClusterStatsNodesResponse struct {\n\tTotal      int                    `json:\"total\"`\n\tSuccessful int                    `json:\"successful\"`\n\tFailed     int                    `json:\"failed\"`\n\tFailures   []*FailedNodeException `json:\"failures,omitempty\"`\n}\n\ntype ClusterStatsIndices struct {\n\tCount      int                            `json:\"count\"` // number of indices\n\tShards     *ClusterStatsIndicesShards     `json:\"shards\"`\n\tDocs       *ClusterStatsIndicesDocs       `json:\"docs\"`\n\tStore      *ClusterStatsIndicesStore      `json:\"store\"`\n\tFieldData  *ClusterStatsIndicesFieldData  `json:\"fielddata\"`\n\tQueryCache *ClusterStatsIndicesQueryCache `json:\"query_cache\"`\n\tCompletion *ClusterStatsIndicesCompletion `json:\"completion\"`\n\tSegments   *IndexStatsSegments            `json:\"segments\"`\n\tAnalysis   *ClusterStatsAnalysisStats     `json:\"analysis\"`\n\tMappings   *ClusterStatsMappingStats      `json:\"mappings\"`\n\tVersions   []*ClusterStatsVersionStats    `json:\"versions\"`\n}\n\ntype ClusterStatsAnalysisStats struct {\n\tCharFilterTypes    []IndexFeatureStats `json:\"char_filter_types,omitempty\"`\n\tTokenizerTypes     []IndexFeatureStats `json:\"tokenizer_types,omitempty\"`\n\tFilterTypes        []IndexFeatureStats `json:\"filter_types,omitempty\"`\n\tAnalyzerTypes      []IndexFeatureStats `json:\"analyzer_types,omitempty\"`\n\tBuiltInCharFilters []IndexFeatureStats `json:\"built_in_char_filters,omitempty\"`\n\tBuiltInTokenizers  []IndexFeatureStats `json:\"built_in_tokenizers,omitempty\"`\n\tBuiltInFilters     []IndexFeatureStats `json:\"built_in_filters,omitempty\"`\n\tBuiltInAnalyzers   []IndexFeatureStats `json:\"built_in_analyzers,omitempty\"`\n}\n\ntype ClusterStatsMappingStats struct {\n\tFieldTypes        []IndexFeatureStats `json:\"field_types\"`\n\tRuntimeFieldTypes []RuntimeFieldStats `json:\"runtime_field_types\"`\n}\n\ntype IndexFeatureStats struct {\n\tName       string `json:\"name\"`\n\tCount      int    `json:\"count\"`\n\tIndexCount int    `json:\"index_count\"`\n\n\tScriptCount int `json:\"script_count\"`\n}\n\ntype RuntimeFieldStats struct {\n\tName            string   `json:\"name\"`\n\tCount           int      `json:\"count\"`\n\tIndexCount      int      `json:\"index_count\"`\n\tScriptlessCount int      `json:\"scriptless_count\"`\n\tShadowedCount   int      `json:\"shadowed_count\"`\n\tLang            []string `json:\"lang\"`\n\n\t// FieldScriptStats\n\n\tLinesMax    int64 `json:\"lines_max\"`\n\tLinesTotal  int64 `json:\"lines_total\"`\n\tCharsMax    int64 `json:\"chars_max\"`\n\tCharsTotal  int64 `json:\"chars_total\"`\n\tSourceMax   int64 `json:\"source_max\"`\n\tSourceTotal int64 `json:\"source_total\"`\n\tDocMax      int64 `json:\"doc_max\"`\n\tDocTotal    int64 `json:\"doc_total\"`\n}\n\ntype FieldScriptStats struct {\n\tLinesMax    int64 `json:\"lines_max\"`\n\tLinesTotal  int64 `json:\"lines_total\"`\n\tCharsMax    int64 `json:\"chars_max\"`\n\tCharsTotal  int64 `json:\"chars_total\"`\n\tSourceMax   int64 `json:\"source_max\"`\n\tSourceTotal int64 `json:\"source_total\"`\n\tDocMax      int64 `json:\"doc_max\"`\n\tDocTotal    int64 `json:\"doc_total\"`\n}\n\ntype ClusterStatsVersionStats struct {\n\tVersion           string `json:\"version\"`\n\tIndexCount        int    `json:\"index_count\"`\n\tPrimaryShardCount int    `json:\"primary_shard_count\"`\n\tTotalPrimarySize  string `json:\"total_primary_size,omitempty\"`\n\tTotalPrimaryBytes int64  `json:\"total_primary_bytes,omitempty\"`\n}\n\ntype ClusterStatsIndicesShards struct {\n\tTotal       int                             `json:\"total\"`\n\tPrimaries   int                             `json:\"primaries\"`\n\tReplication float64                         `json:\"replication\"`\n\tIndex       *ClusterStatsIndicesShardsIndex `json:\"index\"`\n}\n\ntype ClusterStatsIndicesShardsIndex struct {\n\tShards      *ClusterStatsIndicesShardsIndexIntMinMax     `json:\"shards\"`\n\tPrimaries   *ClusterStatsIndicesShardsIndexIntMinMax     `json:\"primaries\"`\n\tReplication *ClusterStatsIndicesShardsIndexFloat64MinMax `json:\"replication\"`\n}\n\ntype ClusterStatsIndicesShardsIndexIntMinMax struct {\n\tMin int     `json:\"min\"`\n\tMax int     `json:\"max\"`\n\tAvg float64 `json:\"avg\"`\n}\n\ntype ClusterStatsIndicesShardsIndexFloat64MinMax struct {\n\tMin float64 `json:\"min\"`\n\tMax float64 `json:\"max\"`\n\tAvg float64 `json:\"avg\"`\n}\n\ntype ClusterStatsIndicesDocs struct {\n\tCount   int `json:\"count\"`\n\tDeleted int `json:\"deleted\"`\n}\n\ntype ClusterStatsIndicesStore struct {\n\tSize                    string `json:\"size\"` // e.g. \"5.3gb\"\n\tSizeInBytes             int64  `json:\"size_in_bytes\"`\n\tTotalDataSetSize        string `json:\"total_data_set_size,omitempty\"`\n\tTotalDataSetSizeInBytes int64  `json:\"total_data_set_size_in_bytes,omitempty\"`\n\tReserved                string `json:\"reserved,omitempty\"`\n\tReservedInBytes         int64  `json:\"reserved_in_bytes,omitempty\"`\n}\n\ntype ClusterStatsIndicesFieldData struct {\n\tMemorySize        string `json:\"memory_size\"` // e.g. \"61.3kb\"\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes\"`\n\tEvictions         int64  `json:\"evictions\"`\n\tFields            map[string]struct {\n\t\tMemorySize        string `json:\"memory_size\"` // e.g. \"61.3kb\"\n\t\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes\"`\n\t} `json:\"fields,omitempty\"`\n}\n\ntype ClusterStatsIndicesQueryCache struct {\n\tMemorySize        string `json:\"memory_size\"` // e.g. \"61.3kb\"\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes\"`\n\tTotalCount        int64  `json:\"total_count\"`\n\tHitCount          int64  `json:\"hit_count\"`\n\tMissCount         int64  `json:\"miss_count\"`\n\tCacheSize         int64  `json:\"cache_size\"`\n\tCacheCount        int64  `json:\"cache_count\"`\n\tEvictions         int64  `json:\"evictions\"`\n}\n\ntype ClusterStatsIndicesCompletion struct {\n\tSize        string `json:\"size\"` // e.g. \"61.3kb\"\n\tSizeInBytes int64  `json:\"size_in_bytes\"`\n\tFields      map[string]struct {\n\t\tSize        string `json:\"size\"` // e.g. \"61.3kb\"\n\t\tSizeInBytes int64  `json:\"size_in_bytes\"`\n\t} `json:\"fields,omitempty\"`\n}\n\ntype ClusterStatsIndicesSegmentsFile struct {\n\tSize        string `json:\"size\"` // e.g. \"61.3kb\"\n\tSizeInBytes int64  `json:\"size_in_bytes\"`\n\tDescription string `json:\"description,omitempty\"`\n}\n\n// ---\n\ntype ClusterStatsNodes struct {\n\tCount    *ClusterStatsNodesCount        `json:\"count\"`\n\tVersions []string                       `json:\"versions\"`\n\tOS       *ClusterStatsNodesOsStats      `json:\"os\"`\n\tProcess  *ClusterStatsNodesProcessStats `json:\"process\"`\n\tJVM      *ClusterStatsNodesJvmStats     `json:\"jvm\"`\n\tFS       *ClusterStatsNodesFsStats      `json:\"fs\"`\n\tPlugins  []*ClusterStatsNodesPlugin     `json:\"plugins\"`\n\n\tNetworkTypes   *ClusterStatsNodesNetworkTypes   `json:\"network_types\"`\n\tDiscoveryTypes *ClusterStatsNodesDiscoveryTypes `json:\"discovery_types\"`\n\tPackagingTypes *ClusterStatsNodesPackagingTypes `json:\"packaging_types\"`\n\n\tIngest *ClusterStatsNodesIngest `json:\"ingest\"`\n}\n\ntype ClusterStatsNodesCount struct {\n\tTotal               int `json:\"total\"`\n\tData                int `json:\"data\"`\n\tDataCold            int `json:\"data_cold\"`\n\tDataContent         int `json:\"data_content\"`\n\tDataFrozen          int `json:\"data_frozen\"`\n\tDataHot             int `json:\"data_hot\"`\n\tDataWarm            int `json:\"data_warm\"`\n\tCoordinatingOnly    int `json:\"coordinating_only\"`\n\tMaster              int `json:\"master\"`\n\tIngest              int `json:\"ingest\"`\n\tML                  int `json:\"ml\"`\n\tRemoteClusterClient int `json:\"remote_cluster_client\"`\n\tTransform           int `json:\"transform\"`\n\tVotingOnly          int `json:\"voting_only\"`\n}\n\ntype ClusterStatsNodesOsStats struct {\n\tAvailableProcessors int `json:\"available_processors\"`\n\tAllocatedProcessors int `json:\"allocated_processors\"`\n\tNames               []struct {\n\t\tName  string `json:\"name\"`\n\t\tValue int    `json:\"count\"`\n\t} `json:\"names\"`\n\tPrettyNames []struct {\n\t\tPrettyName string `json:\"pretty_name\"`\n\t\tValue      int    `json:\"count\"`\n\t} `json:\"pretty_names\"`\n\tMem           *ClusterStatsNodesOsStatsMem `json:\"mem\"`\n\tArchitectures []struct {\n\t\tArch  string `json:\"arch\"`\n\t\tCount int    `json:\"count\"`\n\t} `json:\"architectures\"`\n\t// CPU []*ClusterStatsNodesOsStatsCPU `json:\"cpu\"`\n}\n\ntype ClusterStatsNodesOsStatsMem struct {\n\tTotal        string `json:\"total\"` // e.g. \"16gb\"\n\tTotalInBytes int64  `json:\"total_in_bytes\"`\n\tFree         string `json:\"free\"` // e.g. \"12gb\"\n\tFreeInBytes  int64  `json:\"free_in_bytes\"`\n\tUsed         string `json:\"used\"` // e.g. \"4gb\"\n\tUsedInBytes  int64  `json:\"used_in_bytes\"`\n\tFreePercent  int    `json:\"free_percent\"`\n\tUsedPercent  int    `json:\"used_percent\"`\n}\n\ntype ClusterStatsNodesOsStatsCPU struct {\n\tVendor           string `json:\"vendor\"`\n\tModel            string `json:\"model\"`\n\tMHz              int    `json:\"mhz\"`\n\tTotalCores       int    `json:\"total_cores\"`\n\tTotalSockets     int    `json:\"total_sockets\"`\n\tCoresPerSocket   int    `json:\"cores_per_socket\"`\n\tCacheSize        string `json:\"cache_size\"` // e.g. \"256b\"\n\tCacheSizeInBytes int64  `json:\"cache_size_in_bytes\"`\n\tCount            int    `json:\"count\"`\n}\n\ntype ClusterStatsNodesProcessStats struct {\n\tCPU                 *ClusterStatsNodesProcessStatsCPU                 `json:\"cpu\"`\n\tOpenFileDescriptors *ClusterStatsNodesProcessStatsOpenFileDescriptors `json:\"open_file_descriptors\"`\n}\n\ntype ClusterStatsNodesProcessStatsCPU struct {\n\tPercent float64 `json:\"percent\"`\n}\n\ntype ClusterStatsNodesProcessStatsOpenFileDescriptors struct {\n\tMin int64 `json:\"min\"`\n\tMax int64 `json:\"max\"`\n\tAvg int64 `json:\"avg\"`\n}\n\ntype ClusterStatsNodesJvmStats struct {\n\tMaxUptime         string                              `json:\"max_uptime\"` // e.g. \"5h\"\n\tMaxUptimeInMillis int64                               `json:\"max_uptime_in_millis\"`\n\tVersions          []*ClusterStatsNodesJvmStatsVersion `json:\"versions\"`\n\tMem               *ClusterStatsNodesJvmStatsMem       `json:\"mem\"`\n\tThreads           int64                               `json:\"threads\"`\n}\n\ntype ClusterStatsNodesJvmStatsVersion struct {\n\tVersion         string `json:\"version\"`    // e.g. \"1.8.0_45\"\n\tVMName          string `json:\"vm_name\"`    // e.g. \"Java HotSpot(TM) 64-Bit Server VM\"\n\tVMVersion       string `json:\"vm_version\"` // e.g. \"25.45-b02\"\n\tVMVendor        string `json:\"vm_vendor\"`  // e.g. \"Oracle Corporation\"\n\tBundledJDK      bool   `json:\"bundled_jdk\"`\n\tUsingBundledJDK bool   `json:\"using_bundled_jdk\"`\n\tCount           int    `json:\"count\"`\n}\n\ntype ClusterStatsNodesJvmStatsMem struct {\n\tHeapUsed        string `json:\"heap_used\"`\n\tHeapUsedInBytes int64  `json:\"heap_used_in_bytes\"`\n\tHeapMax         string `json:\"heap_max\"`\n\tHeapMaxInBytes  int64  `json:\"heap_max_in_bytes\"`\n}\n\ntype ClusterStatsNodesFsStats struct {\n\tPath                 string `json:\"path\"`\n\tMount                string `json:\"mount\"`\n\tDev                  string `json:\"dev\"`\n\tTotal                string `json:\"total\"` // e.g. \"930.7gb\"`\n\tTotalInBytes         int64  `json:\"total_in_bytes\"`\n\tFree                 string `json:\"free\"` // e.g. \"930.7gb\"`\n\tFreeInBytes          int64  `json:\"free_in_bytes\"`\n\tAvailable            string `json:\"available\"` // e.g. \"930.7gb\"`\n\tAvailableInBytes     int64  `json:\"available_in_bytes\"`\n\tDiskReads            int64  `json:\"disk_reads\"`\n\tDiskWrites           int64  `json:\"disk_writes\"`\n\tDiskIOOp             int64  `json:\"disk_io_op\"`\n\tDiskReadSize         string `json:\"disk_read_size\"` // e.g. \"0b\"`\n\tDiskReadSizeInBytes  int64  `json:\"disk_read_size_in_bytes\"`\n\tDiskWriteSize        string `json:\"disk_write_size\"` // e.g. \"0b\"`\n\tDiskWriteSizeInBytes int64  `json:\"disk_write_size_in_bytes\"`\n\tDiskIOSize           string `json:\"disk_io_size\"` // e.g. \"0b\"`\n\tDiskIOSizeInBytes    int64  `json:\"disk_io_size_in_bytes\"`\n\tDiskQueue            string `json:\"disk_queue\"`\n\tDiskServiceTime      string `json:\"disk_service_time\"`\n}\n\ntype ClusterStatsNodesPlugin struct {\n\tName        string `json:\"name\"`\n\tVersion     string `json:\"version\"`\n\tDescription string `json:\"description\"`\n\tURL         string `json:\"url\"`\n\tJVM         bool   `json:\"jvm\"`\n\tSite        bool   `json:\"site\"`\n}\n\ntype ClusterStatsNodesNetworkTypes struct {\n\tTransportTypes map[string]interface{} `json:\"transport_types\"` // e.g. \"netty4\": 1\n\tHTTPTypes      map[string]interface{} `json:\"http_types\"`      // e.g. \"netty4\": 1\n}\n\ntype ClusterStatsNodesDiscoveryTypes interface{}\n\ntype ClusterStatsNodesPackagingTypes []*ClusterStatsNodesPackagingType\n\ntype ClusterStatsNodesPackagingType struct {\n\tFlavor string `json:\"flavor\"` // e.g. \"oss\"\n\tType   string `json:\"type\"`   // e.g. \"docker\"\n\tCount  int    `json:\"count\"`  // e.g. 1\n}\n\ntype ClusterStatsNodesIngest struct {\n\tNumberOfPipelines int                    `json:\"number_of_pipelines\"`\n\tProcessorStats    map[string]interface{} `json:\"processor_stats\"`\n}\n"
  },
  {
    "path": "cluster_stats_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestClusterStats(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Get cluster stats\n\tres, err := client.ClusterStats().Human(true).Pretty(true).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected res to be != nil; got: %v\", res)\n\t}\n\tif res.ClusterName == \"\" {\n\t\tt.Fatalf(\"expected a cluster name; got: %q\", res.ClusterName)\n\t}\n\tif res.Nodes == nil {\n\t\tt.Fatalf(\"expected nodes; got: %v\", res.Nodes)\n\t}\n\tif res.Nodes.Count == nil {\n\t\tt.Fatalf(\"expected nodes count; got: %v\", res.Nodes.Count)\n\t}\n}\n"
  },
  {
    "path": "cluster_stats_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"net/url\"\n\t\"testing\"\n)\n\nfunc TestClusterStatsURLs(t *testing.T) {\n\tfFlag := false\n\ttFlag := true\n\n\ttests := []struct {\n\t\tService        *ClusterStatsService\n\t\tExpectedPath   string\n\t\tExpectedParams url.Values\n\t}{\n\t\t{\n\t\t\tService: &ClusterStatsService{\n\t\t\t\tnodeId: []string{},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/stats\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterStatsService{\n\t\t\t\tnodeId: []string{\"node1\"},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/stats/nodes/node1\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterStatsService{\n\t\t\t\tnodeId: []string{\"node1\", \"node2\"},\n\t\t\t},\n\t\t\tExpectedPath: \"/_cluster/stats/nodes/node1%2Cnode2\",\n\t\t},\n\t\t{\n\t\t\tService: &ClusterStatsService{\n\t\t\t\tnodeId:       []string{},\n\t\t\t\tflatSettings: &tFlag,\n\t\t\t},\n\t\t\tExpectedPath:   \"/_cluster/stats\",\n\t\t\tExpectedParams: url.Values{\"flat_settings\": []string{\"true\"}},\n\t\t},\n\t\t{\n\t\t\tService: &ClusterStatsService{\n\t\t\t\tnodeId:       []string{\"node1\"},\n\t\t\t\tflatSettings: &fFlag,\n\t\t\t},\n\t\t\tExpectedPath:   \"/_cluster/stats/nodes/node1\",\n\t\t\tExpectedParams: url.Values{\"flat_settings\": []string{\"false\"}},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tgotPath, gotParams, err := test.Service.buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t\t}\n\t\tif gotPath != test.ExpectedPath {\n\t\t\tt.Errorf(\"expected URL path = %q; got: %q\", test.ExpectedPath, gotPath)\n\t\t}\n\t\tif gotParams.Encode() != test.ExpectedParams.Encode() {\n\t\t\tt.Errorf(\"expected URL params = %v; got: %v\", test.ExpectedParams, gotParams)\n\t\t}\n\t}\n}\n\n// -- TestClusterStatsErrorResponse --\n\nvar clusterStatsErrorResponseTests = []struct {\n\tBody                       string\n\tExpectedNodesStatsFailures int\n}{\n\t// #0\n\t{\n\t\tBody: `{\n\t\t\t\"_nodes\": {\n\t\t\t\t\"total\": 2,\n\t\t\t\t\"successful\": 1,\n\t\t\t\t\"failed\": 1,\n\t\t\t\t\"failures\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"type\": \"failed_node_exception\",\n\t\t\t\t\t\t\"reason\": \"Failed node [mhUZF1sPTcu2b-pIJfqQRg]\",\n\t\t\t\t\t\t\"node_id\": \"mhUZF1sPTcu2b-pIJfqQRg\",\n\t\t\t\t\t\t\"caused_by\": {\n\t\t\t\t\t\t\t\"type\": \"node_not_connected_exception\",\n\t\t\t\t\t\t\t\"reason\": \"[es02][172.27.0.2:9300] Node not connected\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t\t\"cluster_name\": \"es-docker-cluster\",\n\t\t\t\"cluster_uuid\": \"r-OkEGlJTFOE8wP36G-VSg\",\n\t\t\t\"timestamp\": 1621834319499,\n\t\t\t\"indices\": {\n\t\t\t\t\"count\": 0,\n\t\t\t\t\"shards\": {},\n\t\t\t\t\"docs\": {\n\t\t\t\t\t\"count\": 0,\n\t\t\t\t\t\"deleted\": 0\n\t\t\t\t},\n\t\t\t\t\"store\": {\n\t\t\t\t\t\"size_in_bytes\": 0,\n\t\t\t\t\t\"reserved_in_bytes\": 0\n\t\t\t\t},\n\t\t\t\t\"fielddata\": {\n\t\t\t\t\t\"memory_size_in_bytes\": 0,\n\t\t\t\t\t\"evictions\": 0\n\t\t\t\t},\n\t\t\t\t\"query_cache\": {\n\t\t\t\t\t\"memory_size_in_bytes\": 0,\n\t\t\t\t\t\"total_count\": 0,\n\t\t\t\t\t\"hit_count\": 0,\n\t\t\t\t\t\"miss_count\": 0,\n\t\t\t\t\t\"cache_size\": 0,\n\t\t\t\t\t\"cache_count\": 0,\n\t\t\t\t\t\"evictions\": 0\n\t\t\t\t},\n\t\t\t\t\"completion\": {\n\t\t\t\t\t\"size_in_bytes\": 0\n\t\t\t\t},\n\t\t\t\t\"segments\": {\n\t\t\t\t\t\"count\": 0,\n\t\t\t\t\t\"memory_in_bytes\": 0,\n\t\t\t\t\t\"terms_memory_in_bytes\": 0,\n\t\t\t\t\t\"stored_fields_memory_in_bytes\": 0,\n\t\t\t\t\t\"term_vectors_memory_in_bytes\": 0,\n\t\t\t\t\t\"norms_memory_in_bytes\": 0,\n\t\t\t\t\t\"points_memory_in_bytes\": 0,\n\t\t\t\t\t\"doc_values_memory_in_bytes\": 0,\n\t\t\t\t\t\"index_writer_memory_in_bytes\": 0,\n\t\t\t\t\t\"version_map_memory_in_bytes\": 0,\n\t\t\t\t\t\"fixed_bit_set_memory_in_bytes\": 0,\n\t\t\t\t\t\"max_unsafe_auto_id_timestamp\": -9223372036854775808,\n\t\t\t\t\t\"file_sizes\": {}\n\t\t\t\t},\n\t\t\t\t\"mappings\": {\n\t\t\t\t\t\"field_types\": []\n\t\t\t\t},\n\t\t\t\t\"analysis\": {\n\t\t\t\t\t\"char_filter_types\": [],\n\t\t\t\t\t\"tokenizer_types\": [],\n\t\t\t\t\t\"filter_types\": [],\n\t\t\t\t\t\"analyzer_types\": [],\n\t\t\t\t\t\"built_in_char_filters\": [],\n\t\t\t\t\t\"built_in_tokenizers\": [],\n\t\t\t\t\t\"built_in_filters\": [],\n\t\t\t\t\t\"built_in_analyzers\": []\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"nodes\": {\n\t\t\t\t\"count\": {\n\t\t\t\t\t\"total\": 1,\n\t\t\t\t\t\"coordinating_only\": 0,\n\t\t\t\t\t\"data\": 1,\n\t\t\t\t\t\"data_cold\": 1,\n\t\t\t\t\t\"data_content\": 1,\n\t\t\t\t\t\"data_hot\": 1,\n\t\t\t\t\t\"data_warm\": 1,\n\t\t\t\t\t\"ingest\": 1,\n\t\t\t\t\t\"master\": 1,\n\t\t\t\t\t\"ml\": 1,\n\t\t\t\t\t\"remote_cluster_client\": 1,\n\t\t\t\t\t\"transform\": 1,\n\t\t\t\t\t\"voting_only\": 0\n\t\t\t\t},\n\t\t\t\t\"versions\": [\n\t\t\t\t\t\"7.10.0\"\n\t\t\t\t],\n\t\t\t\t\"os\": {\n\t\t\t\t\t\"available_processors\": 6,\n\t\t\t\t\t\"allocated_processors\": 6,\n\t\t\t\t\t\"names\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"name\": \"Linux\",\n\t\t\t\t\t\t\t\"count\": 1\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"pretty_names\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"pretty_name\": \"CentOS Linux 8 (Core)\",\n\t\t\t\t\t\t\t\"count\": 1\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"mem\": {\n\t\t\t\t\t\t\"total_in_bytes\": 2084679680,\n\t\t\t\t\t\t\"free_in_bytes\": 590282752,\n\t\t\t\t\t\t\"used_in_bytes\": 1494396928,\n\t\t\t\t\t\t\"free_percent\": 28,\n\t\t\t\t\t\t\"used_percent\": 72\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"process\": {\n\t\t\t\t\t\"cpu\": {\n\t\t\t\t\t\t\"percent\": 0\n\t\t\t\t\t},\n\t\t\t\t\t\"open_file_descriptors\": {\n\t\t\t\t\t\t\"min\": 260,\n\t\t\t\t\t\t\"max\": 260,\n\t\t\t\t\t\t\"avg\": 260\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"jvm\": {\n\t\t\t\t\t\"max_uptime_in_millis\": 1042623,\n\t\t\t\t\t\"versions\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"version\": \"15.0.1\",\n\t\t\t\t\t\t\t\"vm_name\": \"OpenJDK 64-Bit Server VM\",\n\t\t\t\t\t\t\t\"vm_version\": \"15.0.1+9\",\n\t\t\t\t\t\t\t\"vm_vendor\": \"AdoptOpenJDK\",\n\t\t\t\t\t\t\t\"bundled_jdk\": true,\n\t\t\t\t\t\t\t\"using_bundled_jdk\": true,\n\t\t\t\t\t\t\t\"count\": 1\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\t\"mem\": {\n\t\t\t\t\t\t\"heap_used_in_bytes\": 208299344,\n\t\t\t\t\t\t\"heap_max_in_bytes\": 314572800\n\t\t\t\t\t},\n\t\t\t\t\t\"threads\": 32\n\t\t\t\t},\n\t\t\t\t\"fs\": {\n\t\t\t\t\t\"total_in_bytes\": 62725623808,\n\t\t\t\t\t\"free_in_bytes\": 26955173888,\n\t\t\t\t\t\"available_in_bytes\": 23738458112\n\t\t\t\t},\n\t\t\t\t\"plugins\": [],\n\t\t\t\t\"network_types\": {\n\t\t\t\t\t\"transport_types\": {\n\t\t\t\t\t\t\"security4\": 1\n\t\t\t\t\t},\n\t\t\t\t\t\"http_types\": {\n\t\t\t\t\t\t\"security4\": 1\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"discovery_types\": {\n\t\t\t\t\t\"zen\": 1\n\t\t\t\t},\n\t\t\t\t\"packaging_types\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"flavor\": \"default\",\n\t\t\t\t\t\t\"type\": \"docker\",\n\t\t\t\t\t\t\"count\": 1\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\t\"ingest\": {\n\t\t\t\t\t\"number_of_pipelines\": 0,\n\t\t\t\t\t\"processor_stats\": {}\n\t\t\t\t}\n\t\t\t}\n\t\t}`,\n\t\tExpectedNodesStatsFailures: 1,\n\t},\n\t// #1 7.13.2 happy path\n\t{\n\t\tBody: `{\n\t\t\t\"_nodes\" : {\n\t\t\t  \"total\" : 3,\n\t\t\t  \"successful\" : 3,\n\t\t\t  \"failed\" : 0\n\t\t\t},\n\t\t\t\"cluster_name\" : \"elasticsearch\",\n\t\t\t\"cluster_uuid\" : \"8TTeQMxRSZmffmYcTjP21w\",\n\t\t\t\"timestamp\" : 1625645280402,\n\t\t\t\"status\" : \"green\",\n\t\t\t\"indices\" : {\n\t\t\t  \"count\" : 0,\n\t\t\t  \"shards\" : { },\n\t\t\t  \"docs\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"deleted\" : 0\n\t\t\t  },\n\t\t\t  \"store\" : {\n\t\t\t\t\"size_in_bytes\" : 0,\n\t\t\t\t\"total_data_set_size_in_bytes\" : 0,\n\t\t\t\t\"reserved_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"fielddata\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"query_cache\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"total_count\" : 0,\n\t\t\t\t\"hit_count\" : 0,\n\t\t\t\t\"miss_count\" : 0,\n\t\t\t\t\"cache_size\" : 0,\n\t\t\t\t\"cache_count\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"completion\" : {\n\t\t\t\t\"size_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"segments\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"memory_in_bytes\" : 0,\n\t\t\t\t\"terms_memory_in_bytes\" : 0,\n\t\t\t\t\"stored_fields_memory_in_bytes\" : 0,\n\t\t\t\t\"term_vectors_memory_in_bytes\" : 0,\n\t\t\t\t\"norms_memory_in_bytes\" : 0,\n\t\t\t\t\"points_memory_in_bytes\" : 0,\n\t\t\t\t\"doc_values_memory_in_bytes\" : 0,\n\t\t\t\t\"index_writer_memory_in_bytes\" : 0,\n\t\t\t\t\"version_map_memory_in_bytes\" : 0,\n\t\t\t\t\"fixed_bit_set_memory_in_bytes\" : 0,\n\t\t\t\t\"max_unsafe_auto_id_timestamp\" : -9223372036854775808,\n\t\t\t\t\"file_sizes\" : { }\n\t\t\t  },\n\t\t\t  \"mappings\" : {\n\t\t\t\t\"field_types\" : [ ],\n\t\t\t\t\"runtime_field_types\" : [ ]\n\t\t\t  },\n\t\t\t  \"analysis\" : {\n\t\t\t\t\"char_filter_types\" : [ ],\n\t\t\t\t\"tokenizer_types\" : [ ],\n\t\t\t\t\"filter_types\" : [ ],\n\t\t\t\t\"analyzer_types\" : [ ],\n\t\t\t\t\"built_in_char_filters\" : [ ],\n\t\t\t\t\"built_in_tokenizers\" : [ ],\n\t\t\t\t\"built_in_filters\" : [ ],\n\t\t\t\t\"built_in_analyzers\" : [ ]\n\t\t\t  },\n\t\t\t  \"versions\" : [ ]\n\t\t\t},\n\t\t\t\"nodes\" : {\n\t\t\t  \"count\" : {\n\t\t\t\t\"total\" : 3,\n\t\t\t\t\"coordinating_only\" : 0,\n\t\t\t\t\"data\" : 3,\n\t\t\t\t\"data_cold\" : 3,\n\t\t\t\t\"data_content\" : 3,\n\t\t\t\t\"data_frozen\" : 3,\n\t\t\t\t\"data_hot\" : 3,\n\t\t\t\t\"data_warm\" : 3,\n\t\t\t\t\"ingest\" : 3,\n\t\t\t\t\"master\" : 3,\n\t\t\t\t\"ml\" : 3,\n\t\t\t\t\"remote_cluster_client\" : 3,\n\t\t\t\t\"transform\" : 3,\n\t\t\t\t\"voting_only\" : 0\n\t\t\t  },\n\t\t\t  \"versions\" : [\n\t\t\t\t\"7.13.2\"\n\t\t\t  ],\n\t\t\t  \"os\" : {\n\t\t\t\t\"available_processors\" : 12,\n\t\t\t\t\"allocated_processors\" : 12,\n\t\t\t\t\"names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"name\" : \"Linux\",\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"pretty_names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"pretty_name\" : \"CentOS Linux 8\",\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"architectures\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"arch\" : \"aarch64\",\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"total_in_bytes\" : 25013551104,\n\t\t\t\t  \"free_in_bytes\" : 250650624,\n\t\t\t\t  \"used_in_bytes\" : 24762900480,\n\t\t\t\t  \"free_percent\" : 1,\n\t\t\t\t  \"used_percent\" : 99\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"process\" : {\n\t\t\t\t\"cpu\" : {\n\t\t\t\t  \"percent\" : 0\n\t\t\t\t},\n\t\t\t\t\"open_file_descriptors\" : {\n\t\t\t\t  \"min\" : 329,\n\t\t\t\t  \"max\" : 330,\n\t\t\t\t  \"avg\" : 329\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"jvm\" : {\n\t\t\t\t\"max_uptime_in_millis\" : 119028,\n\t\t\t\t\"versions\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"version\" : \"16\",\n\t\t\t\t\t\"vm_name\" : \"OpenJDK 64-Bit Server VM\",\n\t\t\t\t\t\"vm_version\" : \"16+36\",\n\t\t\t\t\t\"vm_vendor\" : \"AdoptOpenJDK\",\n\t\t\t\t\t\"bundled_jdk\" : true,\n\t\t\t\t\t\"using_bundled_jdk\" : true,\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"heap_used_in_bytes\" : 748080592,\n\t\t\t\t  \"heap_max_in_bytes\" : 3221225472\n\t\t\t\t},\n\t\t\t\t\"threads\" : 87\n\t\t\t  },\n\t\t\t  \"fs\" : {\n\t\t\t\t\"total_in_bytes\" : 481133838336,\n\t\t\t\t\"free_in_bytes\" : 459472416768,\n\t\t\t\t\"available_in_bytes\" : 434940936192\n\t\t\t  },\n\t\t\t  \"plugins\" : [ ],\n\t\t\t  \"network_types\" : {\n\t\t\t\t\"transport_types\" : {\n\t\t\t\t  \"netty4\" : 3\n\t\t\t\t},\n\t\t\t\t\"http_types\" : {\n\t\t\t\t  \"netty4\" : 3\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"discovery_types\" : {\n\t\t\t\t\"zen\" : 3\n\t\t\t  },\n\t\t\t  \"packaging_types\" : [\n\t\t\t\t{\n\t\t\t\t  \"flavor\" : \"default\",\n\t\t\t\t  \"type\" : \"docker\",\n\t\t\t\t  \"count\" : 3\n\t\t\t\t}\n\t\t\t  ],\n\t\t\t  \"ingest\" : {\n\t\t\t\t\"number_of_pipelines\" : 2,\n\t\t\t\t\"processor_stats\" : {\n\t\t\t\t  \"gsub\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  },\n\t\t\t\t  \"script\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  }`,\n\t\tExpectedNodesStatsFailures: 0,\n\t},\n\t// #2 7.13.2 failed nodes\n\t{\n\t\tBody: `{\n\t\t\t\"_nodes\" : {\n\t\t\t  \"total\" : 2,\n\t\t\t  \"successful\" : 1,\n\t\t\t  \"failed\" : 1,\n\t\t\t  \"failures\" : [\n\t\t\t\t{\n\t\t\t\t  \"type\" : \"failed_node_exception\",\n\t\t\t\t  \"reason\" : \"Failed node [agq-C6ZPSYmPgNePwb26_Q]\",\n\t\t\t\t  \"node_id\" : \"agq-C6ZPSYmPgNePwb26_Q\",\n\t\t\t\t  \"caused_by\" : {\n\t\t\t\t\t\"type\" : \"node_not_connected_exception\",\n\t\t\t\t\t\"reason\" : \"[es2][172.23.0.4:9300] Node not connected\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  ]\n\t\t\t},\n\t\t\t\"cluster_name\" : \"elasticsearch\",\n\t\t\t\"cluster_uuid\" : \"8TTeQMxRSZmffmYcTjP21w\",\n\t\t\t\"timestamp\" : 1625645352594,\n\t\t\t\"indices\" : {\n\t\t\t  \"count\" : 0,\n\t\t\t  \"shards\" : { },\n\t\t\t  \"docs\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"deleted\" : 0\n\t\t\t  },\n\t\t\t  \"store\" : {\n\t\t\t\t\"size_in_bytes\" : 0,\n\t\t\t\t\"total_data_set_size_in_bytes\" : 0,\n\t\t\t\t\"reserved_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"fielddata\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"query_cache\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"total_count\" : 0,\n\t\t\t\t\"hit_count\" : 0,\n\t\t\t\t\"miss_count\" : 0,\n\t\t\t\t\"cache_size\" : 0,\n\t\t\t\t\"cache_count\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"completion\" : {\n\t\t\t\t\"size_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"segments\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"memory_in_bytes\" : 0,\n\t\t\t\t\"terms_memory_in_bytes\" : 0,\n\t\t\t\t\"stored_fields_memory_in_bytes\" : 0,\n\t\t\t\t\"term_vectors_memory_in_bytes\" : 0,\n\t\t\t\t\"norms_memory_in_bytes\" : 0,\n\t\t\t\t\"points_memory_in_bytes\" : 0,\n\t\t\t\t\"doc_values_memory_in_bytes\" : 0,\n\t\t\t\t\"index_writer_memory_in_bytes\" : 0,\n\t\t\t\t\"version_map_memory_in_bytes\" : 0,\n\t\t\t\t\"fixed_bit_set_memory_in_bytes\" : 0,\n\t\t\t\t\"max_unsafe_auto_id_timestamp\" : -9223372036854775808,\n\t\t\t\t\"file_sizes\" : { }\n\t\t\t  },\n\t\t\t  \"mappings\" : {\n\t\t\t\t\"field_types\" : [ ],\n\t\t\t\t\"runtime_field_types\" : [ ]\n\t\t\t  },\n\t\t\t  \"analysis\" : {\n\t\t\t\t\"char_filter_types\" : [ ],\n\t\t\t\t\"tokenizer_types\" : [ ],\n\t\t\t\t\"filter_types\" : [ ],\n\t\t\t\t\"analyzer_types\" : [ ],\n\t\t\t\t\"built_in_char_filters\" : [ ],\n\t\t\t\t\"built_in_tokenizers\" : [ ],\n\t\t\t\t\"built_in_filters\" : [ ],\n\t\t\t\t\"built_in_analyzers\" : [ ]\n\t\t\t  },\n\t\t\t  \"versions\" : [ ]\n\t\t\t},\n\t\t\t\"nodes\" : {\n\t\t\t  \"count\" : {\n\t\t\t\t\"total\" : 1,\n\t\t\t\t\"coordinating_only\" : 0,\n\t\t\t\t\"data\" : 1,\n\t\t\t\t\"data_cold\" : 1,\n\t\t\t\t\"data_content\" : 1,\n\t\t\t\t\"data_frozen\" : 1,\n\t\t\t\t\"data_hot\" : 1,\n\t\t\t\t\"data_warm\" : 1,\n\t\t\t\t\"ingest\" : 1,\n\t\t\t\t\"master\" : 1,\n\t\t\t\t\"ml\" : 1,\n\t\t\t\t\"remote_cluster_client\" : 1,\n\t\t\t\t\"transform\" : 1,\n\t\t\t\t\"voting_only\" : 0\n\t\t\t  },\n\t\t\t  \"versions\" : [\n\t\t\t\t\"7.13.2\"\n\t\t\t  ],\n\t\t\t  \"os\" : {\n\t\t\t\t\"available_processors\" : 4,\n\t\t\t\t\"allocated_processors\" : 4,\n\t\t\t\t\"names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"name\" : \"Linux\",\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"pretty_names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"pretty_name\" : \"CentOS Linux 8\",\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"architectures\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"arch\" : \"aarch64\",\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"total_in_bytes\" : 8337850368,\n\t\t\t\t  \"free_in_bytes\" : 2963259392,\n\t\t\t\t  \"used_in_bytes\" : 5374590976,\n\t\t\t\t  \"free_percent\" : 36,\n\t\t\t\t  \"used_percent\" : 64\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"process\" : {\n\t\t\t\t\"cpu\" : {\n\t\t\t\t  \"percent\" : 0\n\t\t\t\t},\n\t\t\t\t\"open_file_descriptors\" : {\n\t\t\t\t  \"min\" : 279,\n\t\t\t\t  \"max\" : 279,\n\t\t\t\t  \"avg\" : 279\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"jvm\" : {\n\t\t\t\t\"max_uptime_in_millis\" : 189845,\n\t\t\t\t\"versions\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"version\" : \"16\",\n\t\t\t\t\t\"vm_name\" : \"OpenJDK 64-Bit Server VM\",\n\t\t\t\t\t\"vm_version\" : \"16+36\",\n\t\t\t\t\t\"vm_vendor\" : \"AdoptOpenJDK\",\n\t\t\t\t\t\"bundled_jdk\" : true,\n\t\t\t\t\t\"using_bundled_jdk\" : true,\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"heap_used_in_bytes\" : 315085776,\n\t\t\t\t  \"heap_max_in_bytes\" : 1073741824\n\t\t\t\t},\n\t\t\t\t\"threads\" : 34\n\t\t\t  },\n\t\t\t  \"fs\" : {\n\t\t\t\t\"total_in_bytes\" : 160377946112,\n\t\t\t\t\"free_in_bytes\" : 153157689344,\n\t\t\t\t\"available_in_bytes\" : 144980529152\n\t\t\t  },\n\t\t\t  \"plugins\" : [ ],\n\t\t\t  \"network_types\" : {\n\t\t\t\t\"transport_types\" : {\n\t\t\t\t  \"netty4\" : 1\n\t\t\t\t},\n\t\t\t\t\"http_types\" : {\n\t\t\t\t  \"netty4\" : 1\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"discovery_types\" : {\n\t\t\t\t\"zen\" : 1\n\t\t\t  },\n\t\t\t  \"packaging_types\" : [\n\t\t\t\t{\n\t\t\t\t  \"flavor\" : \"default\",\n\t\t\t\t  \"type\" : \"docker\",\n\t\t\t\t  \"count\" : 1\n\t\t\t\t}\n\t\t\t  ],\n\t\t\t  \"ingest\" : {\n\t\t\t\t\"number_of_pipelines\" : 1,\n\t\t\t\t\"processor_stats\" : {\n\t\t\t\t  \"gsub\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  },\n\t\t\t\t  \"script\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  }`,\n\t\tExpectedNodesStatsFailures: 1,\n\t},\n\t// #3 7.12.1 happy path\n\t{\n\t\tBody: `{\n\t\t\t\"_nodes\" : {\n\t\t\t  \"total\" : 3,\n\t\t\t  \"successful\" : 3,\n\t\t\t  \"failed\" : 0\n\t\t\t},\n\t\t\t\"cluster_name\" : \"elasticsearch\",\n\t\t\t\"cluster_uuid\" : \"XmKLDCnmRqqK3Ve01uJU0Q\",\n\t\t\t\"timestamp\" : 1625645497836,\n\t\t\t\"status\" : \"green\",\n\t\t\t\"indices\" : {\n\t\t\t  \"count\" : 0,\n\t\t\t  \"shards\" : { },\n\t\t\t  \"docs\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"deleted\" : 0\n\t\t\t  },\n\t\t\t  \"store\" : {\n\t\t\t\t\"size_in_bytes\" : 0,\n\t\t\t\t\"reserved_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"fielddata\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"query_cache\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"total_count\" : 0,\n\t\t\t\t\"hit_count\" : 0,\n\t\t\t\t\"miss_count\" : 0,\n\t\t\t\t\"cache_size\" : 0,\n\t\t\t\t\"cache_count\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"completion\" : {\n\t\t\t\t\"size_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"segments\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"memory_in_bytes\" : 0,\n\t\t\t\t\"terms_memory_in_bytes\" : 0,\n\t\t\t\t\"stored_fields_memory_in_bytes\" : 0,\n\t\t\t\t\"term_vectors_memory_in_bytes\" : 0,\n\t\t\t\t\"norms_memory_in_bytes\" : 0,\n\t\t\t\t\"points_memory_in_bytes\" : 0,\n\t\t\t\t\"doc_values_memory_in_bytes\" : 0,\n\t\t\t\t\"index_writer_memory_in_bytes\" : 0,\n\t\t\t\t\"version_map_memory_in_bytes\" : 0,\n\t\t\t\t\"fixed_bit_set_memory_in_bytes\" : 0,\n\t\t\t\t\"max_unsafe_auto_id_timestamp\" : -9223372036854775808,\n\t\t\t\t\"file_sizes\" : { }\n\t\t\t  },\n\t\t\t  \"mappings\" : {\n\t\t\t\t\"field_types\" : [ ]\n\t\t\t  },\n\t\t\t  \"analysis\" : {\n\t\t\t\t\"char_filter_types\" : [ ],\n\t\t\t\t\"tokenizer_types\" : [ ],\n\t\t\t\t\"filter_types\" : [ ],\n\t\t\t\t\"analyzer_types\" : [ ],\n\t\t\t\t\"built_in_char_filters\" : [ ],\n\t\t\t\t\"built_in_tokenizers\" : [ ],\n\t\t\t\t\"built_in_filters\" : [ ],\n\t\t\t\t\"built_in_analyzers\" : [ ]\n\t\t\t  },\n\t\t\t  \"versions\" : [ ]\n\t\t\t},\n\t\t\t\"nodes\" : {\n\t\t\t  \"count\" : {\n\t\t\t\t\"total\" : 3,\n\t\t\t\t\"coordinating_only\" : 0,\n\t\t\t\t\"data\" : 3,\n\t\t\t\t\"data_cold\" : 3,\n\t\t\t\t\"data_content\" : 3,\n\t\t\t\t\"data_frozen\" : 3,\n\t\t\t\t\"data_hot\" : 3,\n\t\t\t\t\"data_warm\" : 3,\n\t\t\t\t\"ingest\" : 3,\n\t\t\t\t\"master\" : 3,\n\t\t\t\t\"ml\" : 3,\n\t\t\t\t\"remote_cluster_client\" : 3,\n\t\t\t\t\"transform\" : 3,\n\t\t\t\t\"voting_only\" : 0\n\t\t\t  },\n\t\t\t  \"versions\" : [\n\t\t\t\t\"7.12.1\"\n\t\t\t  ],\n\t\t\t  \"os\" : {\n\t\t\t\t\"available_processors\" : 12,\n\t\t\t\t\"allocated_processors\" : 12,\n\t\t\t\t\"names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"name\" : \"Linux\",\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"pretty_names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"pretty_name\" : \"CentOS Linux 8\",\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"architectures\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"arch\" : \"aarch64\",\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"total_in_bytes\" : 25013551104,\n\t\t\t\t  \"free_in_bytes\" : 277807104,\n\t\t\t\t  \"used_in_bytes\" : 24735744000,\n\t\t\t\t  \"free_percent\" : 1,\n\t\t\t\t  \"used_percent\" : 99\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"process\" : {\n\t\t\t\t\"cpu\" : {\n\t\t\t\t  \"percent\" : 1\n\t\t\t\t},\n\t\t\t\t\"open_file_descriptors\" : {\n\t\t\t\t  \"min\" : 332,\n\t\t\t\t  \"max\" : 333,\n\t\t\t\t  \"avg\" : 332\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"jvm\" : {\n\t\t\t\t\"max_uptime_in_millis\" : 36043,\n\t\t\t\t\"versions\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"version\" : \"16\",\n\t\t\t\t\t\"vm_name\" : \"OpenJDK 64-Bit Server VM\",\n\t\t\t\t\t\"vm_version\" : \"16+36\",\n\t\t\t\t\t\"vm_vendor\" : \"AdoptOpenJDK\",\n\t\t\t\t\t\"bundled_jdk\" : true,\n\t\t\t\t\t\"using_bundled_jdk\" : true,\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"heap_used_in_bytes\" : 754473472,\n\t\t\t\t  \"heap_max_in_bytes\" : 3221225472\n\t\t\t\t},\n\t\t\t\t\"threads\" : 91\n\t\t\t  },\n\t\t\t  \"fs\" : {\n\t\t\t\t\"total_in_bytes\" : 481133838336,\n\t\t\t\t\"free_in_bytes\" : 457492058112,\n\t\t\t\t\"available_in_bytes\" : 432960577536\n\t\t\t  },\n\t\t\t  \"plugins\" : [ ],\n\t\t\t  \"network_types\" : {\n\t\t\t\t\"transport_types\" : {\n\t\t\t\t  \"netty4\" : 3\n\t\t\t\t},\n\t\t\t\t\"http_types\" : {\n\t\t\t\t  \"netty4\" : 3\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"discovery_types\" : {\n\t\t\t\t\"zen\" : 3\n\t\t\t  },\n\t\t\t  \"packaging_types\" : [\n\t\t\t\t{\n\t\t\t\t  \"flavor\" : \"default\",\n\t\t\t\t  \"type\" : \"docker\",\n\t\t\t\t  \"count\" : 3\n\t\t\t\t}\n\t\t\t  ],\n\t\t\t  \"ingest\" : {\n\t\t\t\t\"number_of_pipelines\" : 2,\n\t\t\t\t\"processor_stats\" : {\n\t\t\t\t  \"gsub\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  },\n\t\t\t\t  \"script\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  }`,\n\t\tExpectedNodesStatsFailures: 0,\n\t},\n\t// #4 7.12.1 failed nodes\n\t{\n\t\tBody: `{\n\t\t\t\"_nodes\" : {\n\t\t\t  \"total\" : 3,\n\t\t\t  \"successful\" : 1,\n\t\t\t  \"failed\" : 2,\n\t\t\t  \"failures\" : [\n\t\t\t\t{\n\t\t\t\t  \"type\" : \"failed_node_exception\",\n\t\t\t\t  \"reason\" : \"Failed node [eE61wq63TxW0yN1ILeoZ5g]\",\n\t\t\t\t  \"node_id\" : \"eE61wq63TxW0yN1ILeoZ5g\",\n\t\t\t\t  \"caused_by\" : {\n\t\t\t\t\t\"type\" : \"node_not_connected_exception\",\n\t\t\t\t\t\"reason\" : \"[es3][172.24.0.4:9300] Node not connected\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t  \"type\" : \"failed_node_exception\",\n\t\t\t\t  \"reason\" : \"Failed node [AAQlfCf0TJ644wJvjaOSyA]\",\n\t\t\t\t  \"node_id\" : \"AAQlfCf0TJ644wJvjaOSyA\",\n\t\t\t\t  \"caused_by\" : {\n\t\t\t\t\t\"type\" : \"node_not_connected_exception\",\n\t\t\t\t\t\"reason\" : \"[es2][172.24.0.3:9300] Node not connected\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  ]\n\t\t\t},\n\t\t\t\"cluster_name\" : \"elasticsearch\",\n\t\t\t\"cluster_uuid\" : \"XmKLDCnmRqqK3Ve01uJU0Q\",\n\t\t\t\"timestamp\" : 1625645535819,\n\t\t\t\"indices\" : {\n\t\t\t  \"count\" : 0,\n\t\t\t  \"shards\" : { },\n\t\t\t  \"docs\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"deleted\" : 0\n\t\t\t  },\n\t\t\t  \"store\" : {\n\t\t\t\t\"size_in_bytes\" : 0,\n\t\t\t\t\"reserved_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"fielddata\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"query_cache\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"total_count\" : 0,\n\t\t\t\t\"hit_count\" : 0,\n\t\t\t\t\"miss_count\" : 0,\n\t\t\t\t\"cache_size\" : 0,\n\t\t\t\t\"cache_count\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"completion\" : {\n\t\t\t\t\"size_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"segments\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"memory_in_bytes\" : 0,\n\t\t\t\t\"terms_memory_in_bytes\" : 0,\n\t\t\t\t\"stored_fields_memory_in_bytes\" : 0,\n\t\t\t\t\"term_vectors_memory_in_bytes\" : 0,\n\t\t\t\t\"norms_memory_in_bytes\" : 0,\n\t\t\t\t\"points_memory_in_bytes\" : 0,\n\t\t\t\t\"doc_values_memory_in_bytes\" : 0,\n\t\t\t\t\"index_writer_memory_in_bytes\" : 0,\n\t\t\t\t\"version_map_memory_in_bytes\" : 0,\n\t\t\t\t\"fixed_bit_set_memory_in_bytes\" : 0,\n\t\t\t\t\"max_unsafe_auto_id_timestamp\" : -9223372036854775808,\n\t\t\t\t\"file_sizes\" : { }\n\t\t\t  },\n\t\t\t  \"mappings\" : {\n\t\t\t\t\"field_types\" : [ ]\n\t\t\t  },\n\t\t\t  \"analysis\" : {\n\t\t\t\t\"char_filter_types\" : [ ],\n\t\t\t\t\"tokenizer_types\" : [ ],\n\t\t\t\t\"filter_types\" : [ ],\n\t\t\t\t\"analyzer_types\" : [ ],\n\t\t\t\t\"built_in_char_filters\" : [ ],\n\t\t\t\t\"built_in_tokenizers\" : [ ],\n\t\t\t\t\"built_in_filters\" : [ ],\n\t\t\t\t\"built_in_analyzers\" : [ ]\n\t\t\t  },\n\t\t\t  \"versions\" : [ ]\n\t\t\t},\n\t\t\t\"nodes\" : {\n\t\t\t  \"count\" : {\n\t\t\t\t\"total\" : 1,\n\t\t\t\t\"coordinating_only\" : 0,\n\t\t\t\t\"data\" : 1,\n\t\t\t\t\"data_cold\" : 1,\n\t\t\t\t\"data_content\" : 1,\n\t\t\t\t\"data_frozen\" : 1,\n\t\t\t\t\"data_hot\" : 1,\n\t\t\t\t\"data_warm\" : 1,\n\t\t\t\t\"ingest\" : 1,\n\t\t\t\t\"master\" : 1,\n\t\t\t\t\"ml\" : 1,\n\t\t\t\t\"remote_cluster_client\" : 1,\n\t\t\t\t\"transform\" : 1,\n\t\t\t\t\"voting_only\" : 0\n\t\t\t  },\n\t\t\t  \"versions\" : [\n\t\t\t\t\"7.12.1\"\n\t\t\t  ],\n\t\t\t  \"os\" : {\n\t\t\t\t\"available_processors\" : 4,\n\t\t\t\t\"allocated_processors\" : 4,\n\t\t\t\t\"names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"name\" : \"Linux\",\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"pretty_names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"pretty_name\" : \"CentOS Linux 8\",\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"architectures\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"arch\" : \"aarch64\",\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"total_in_bytes\" : 8337850368,\n\t\t\t\t  \"free_in_bytes\" : 2912473088,\n\t\t\t\t  \"used_in_bytes\" : 5425377280,\n\t\t\t\t  \"free_percent\" : 35,\n\t\t\t\t  \"used_percent\" : 65\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"process\" : {\n\t\t\t\t\"cpu\" : {\n\t\t\t\t  \"percent\" : 0\n\t\t\t\t},\n\t\t\t\t\"open_file_descriptors\" : {\n\t\t\t\t  \"min\" : 308,\n\t\t\t\t  \"max\" : 308,\n\t\t\t\t  \"avg\" : 308\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"jvm\" : {\n\t\t\t\t\"max_uptime_in_millis\" : 74067,\n\t\t\t\t\"versions\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"version\" : \"16\",\n\t\t\t\t\t\"vm_name\" : \"OpenJDK 64-Bit Server VM\",\n\t\t\t\t\t\"vm_version\" : \"16+36\",\n\t\t\t\t\t\"vm_vendor\" : \"AdoptOpenJDK\",\n\t\t\t\t\t\"bundled_jdk\" : true,\n\t\t\t\t\t\"using_bundled_jdk\" : true,\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"heap_used_in_bytes\" : 219877888,\n\t\t\t\t  \"heap_max_in_bytes\" : 1073741824\n\t\t\t\t},\n\t\t\t\t\"threads\" : 32\n\t\t\t  },\n\t\t\t  \"fs\" : {\n\t\t\t\t\"total_in_bytes\" : 160377946112,\n\t\t\t\t\"free_in_bytes\" : 152497557504,\n\t\t\t\t\"available_in_bytes\" : 144320397312\n\t\t\t  },\n\t\t\t  \"plugins\" : [ ],\n\t\t\t  \"network_types\" : {\n\t\t\t\t\"transport_types\" : {\n\t\t\t\t  \"netty4\" : 1\n\t\t\t\t},\n\t\t\t\t\"http_types\" : {\n\t\t\t\t  \"netty4\" : 1\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"discovery_types\" : {\n\t\t\t\t\"zen\" : 1\n\t\t\t  },\n\t\t\t  \"packaging_types\" : [\n\t\t\t\t{\n\t\t\t\t  \"flavor\" : \"default\",\n\t\t\t\t  \"type\" : \"docker\",\n\t\t\t\t  \"count\" : 1\n\t\t\t\t}\n\t\t\t  ],\n\t\t\t  \"ingest\" : {\n\t\t\t\t\"number_of_pipelines\" : 1,\n\t\t\t\t\"processor_stats\" : {\n\t\t\t\t  \"gsub\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  },\n\t\t\t\t  \"script\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  }`,\n\t\tExpectedNodesStatsFailures: 2,\n\t},\n\t// #5 7.10.0 happy path\n\t{\n\t\tBody: `{\n\t\t\t\"_nodes\" : {\n\t\t\t  \"total\" : 3,\n\t\t\t  \"successful\" : 3,\n\t\t\t  \"failed\" : 0\n\t\t\t},\n\t\t\t\"cluster_name\" : \"elasticsearch\",\n\t\t\t\"cluster_uuid\" : \"XvRExZcTTqiiYa8Qa0E6LA\",\n\t\t\t\"timestamp\" : 1625645743243,\n\t\t\t\"status\" : \"green\",\n\t\t\t\"indices\" : {\n\t\t\t  \"count\" : 0,\n\t\t\t  \"shards\" : { },\n\t\t\t  \"docs\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"deleted\" : 0\n\t\t\t  },\n\t\t\t  \"store\" : {\n\t\t\t\t\"size_in_bytes\" : 0,\n\t\t\t\t\"reserved_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"fielddata\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"query_cache\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"total_count\" : 0,\n\t\t\t\t\"hit_count\" : 0,\n\t\t\t\t\"miss_count\" : 0,\n\t\t\t\t\"cache_size\" : 0,\n\t\t\t\t\"cache_count\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"completion\" : {\n\t\t\t\t\"size_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"segments\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"memory_in_bytes\" : 0,\n\t\t\t\t\"terms_memory_in_bytes\" : 0,\n\t\t\t\t\"stored_fields_memory_in_bytes\" : 0,\n\t\t\t\t\"term_vectors_memory_in_bytes\" : 0,\n\t\t\t\t\"norms_memory_in_bytes\" : 0,\n\t\t\t\t\"points_memory_in_bytes\" : 0,\n\t\t\t\t\"doc_values_memory_in_bytes\" : 0,\n\t\t\t\t\"index_writer_memory_in_bytes\" : 0,\n\t\t\t\t\"version_map_memory_in_bytes\" : 0,\n\t\t\t\t\"fixed_bit_set_memory_in_bytes\" : 0,\n\t\t\t\t\"max_unsafe_auto_id_timestamp\" : -9223372036854775808,\n\t\t\t\t\"file_sizes\" : { }\n\t\t\t  },\n\t\t\t  \"mappings\" : {\n\t\t\t\t\"field_types\" : [ ]\n\t\t\t  },\n\t\t\t  \"analysis\" : {\n\t\t\t\t\"char_filter_types\" : [ ],\n\t\t\t\t\"tokenizer_types\" : [ ],\n\t\t\t\t\"filter_types\" : [ ],\n\t\t\t\t\"analyzer_types\" : [ ],\n\t\t\t\t\"built_in_char_filters\" : [ ],\n\t\t\t\t\"built_in_tokenizers\" : [ ],\n\t\t\t\t\"built_in_filters\" : [ ],\n\t\t\t\t\"built_in_analyzers\" : [ ]\n\t\t\t  }\n\t\t\t},\n\t\t\t\"nodes\" : {\n\t\t\t  \"count\" : {\n\t\t\t\t\"total\" : 3,\n\t\t\t\t\"coordinating_only\" : 0,\n\t\t\t\t\"data\" : 3,\n\t\t\t\t\"data_cold\" : 3,\n\t\t\t\t\"data_content\" : 3,\n\t\t\t\t\"data_hot\" : 3,\n\t\t\t\t\"data_warm\" : 3,\n\t\t\t\t\"ingest\" : 3,\n\t\t\t\t\"master\" : 3,\n\t\t\t\t\"ml\" : 3,\n\t\t\t\t\"remote_cluster_client\" : 3,\n\t\t\t\t\"transform\" : 3,\n\t\t\t\t\"voting_only\" : 0\n\t\t\t  },\n\t\t\t  \"versions\" : [\n\t\t\t\t\"7.10.0\"\n\t\t\t  ],\n\t\t\t  \"os\" : {\n\t\t\t\t\"available_processors\" : 12,\n\t\t\t\t\"allocated_processors\" : 12,\n\t\t\t\t\"names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"name\" : \"Linux\",\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"pretty_names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"pretty_name\" : \"CentOS Linux 8 (Core)\",\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"total_in_bytes\" : 25013551104,\n\t\t\t\t  \"free_in_bytes\" : 251179008,\n\t\t\t\t  \"used_in_bytes\" : 24762372096,\n\t\t\t\t  \"free_percent\" : 1,\n\t\t\t\t  \"used_percent\" : 99\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"process\" : {\n\t\t\t\t\"cpu\" : {\n\t\t\t\t  \"percent\" : 1\n\t\t\t\t},\n\t\t\t\t\"open_file_descriptors\" : {\n\t\t\t\t  \"min\" : 304,\n\t\t\t\t  \"max\" : 304,\n\t\t\t\t  \"avg\" : 304\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"jvm\" : {\n\t\t\t\t\"max_uptime_in_millis\" : 31334,\n\t\t\t\t\"versions\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"version\" : \"15.0.1\",\n\t\t\t\t\t\"vm_name\" : \"OpenJDK 64-Bit Server VM\",\n\t\t\t\t\t\"vm_version\" : \"15.0.1+9\",\n\t\t\t\t\t\"vm_vendor\" : \"AdoptOpenJDK\",\n\t\t\t\t\t\"bundled_jdk\" : true,\n\t\t\t\t\t\"using_bundled_jdk\" : true,\n\t\t\t\t\t\"count\" : 3\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"heap_used_in_bytes\" : 746485240,\n\t\t\t\t  \"heap_max_in_bytes\" : 3221225472\n\t\t\t\t},\n\t\t\t\t\"threads\" : 93\n\t\t\t  },\n\t\t\t  \"fs\" : {\n\t\t\t\t\"total_in_bytes\" : 481133838336,\n\t\t\t\t\"free_in_bytes\" : 454960951296,\n\t\t\t\t\"available_in_bytes\" : 430429470720\n\t\t\t  },\n\t\t\t  \"plugins\" : [ ],\n\t\t\t  \"network_types\" : {\n\t\t\t\t\"transport_types\" : {\n\t\t\t\t  \"netty4\" : 3\n\t\t\t\t},\n\t\t\t\t\"http_types\" : {\n\t\t\t\t  \"netty4\" : 3\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"discovery_types\" : {\n\t\t\t\t\"zen\" : 3\n\t\t\t  },\n\t\t\t  \"packaging_types\" : [\n\t\t\t\t{\n\t\t\t\t  \"flavor\" : \"default\",\n\t\t\t\t  \"type\" : \"docker\",\n\t\t\t\t  \"count\" : 3\n\t\t\t\t}\n\t\t\t  ],\n\t\t\t  \"ingest\" : {\n\t\t\t\t\"number_of_pipelines\" : 2,\n\t\t\t\t\"processor_stats\" : {\n\t\t\t\t  \"gsub\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  },\n\t\t\t\t  \"script\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  }`,\n\t\tExpectedNodesStatsFailures: 0,\n\t},\n\t// #6 7.10.1 failed nodes\n\t{\n\t\tBody: `{\n\t\t\t\"_nodes\" : {\n\t\t\t  \"total\" : 3,\n\t\t\t  \"successful\" : 1,\n\t\t\t  \"failed\" : 2,\n\t\t\t  \"failures\" : [\n\t\t\t\t{\n\t\t\t\t  \"type\" : \"failed_node_exception\",\n\t\t\t\t  \"reason\" : \"Failed node [fkiRoRjkQY-oij3qaBW9CQ]\",\n\t\t\t\t  \"node_id\" : \"fkiRoRjkQY-oij3qaBW9CQ\",\n\t\t\t\t  \"caused_by\" : {\n\t\t\t\t\t\"type\" : \"node_not_connected_exception\",\n\t\t\t\t\t\"reason\" : \"[es2][172.25.0.3:9300] Node not connected\"\n\t\t\t\t  }\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t  \"type\" : \"failed_node_exception\",\n\t\t\t\t  \"reason\" : \"Failed node [-fP8gimVQLu2tQV8luneBQ]\",\n\t\t\t\t  \"node_id\" : \"-fP8gimVQLu2tQV8luneBQ\",\n\t\t\t\t  \"caused_by\" : {\n\t\t\t\t\t\"type\" : \"node_not_connected_exception\",\n\t\t\t\t\t\"reason\" : \"[es3][172.25.0.4:9300] Node not connected\"\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  ]\n\t\t\t},\n\t\t\t\"cluster_name\" : \"elasticsearch\",\n\t\t\t\"cluster_uuid\" : \"XvRExZcTTqiiYa8Qa0E6LA\",\n\t\t\t\"timestamp\" : 1625645771492,\n\t\t\t\"indices\" : {\n\t\t\t  \"count\" : 0,\n\t\t\t  \"shards\" : { },\n\t\t\t  \"docs\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"deleted\" : 0\n\t\t\t  },\n\t\t\t  \"store\" : {\n\t\t\t\t\"size_in_bytes\" : 0,\n\t\t\t\t\"reserved_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"fielddata\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"query_cache\" : {\n\t\t\t\t\"memory_size_in_bytes\" : 0,\n\t\t\t\t\"total_count\" : 0,\n\t\t\t\t\"hit_count\" : 0,\n\t\t\t\t\"miss_count\" : 0,\n\t\t\t\t\"cache_size\" : 0,\n\t\t\t\t\"cache_count\" : 0,\n\t\t\t\t\"evictions\" : 0\n\t\t\t  },\n\t\t\t  \"completion\" : {\n\t\t\t\t\"size_in_bytes\" : 0\n\t\t\t  },\n\t\t\t  \"segments\" : {\n\t\t\t\t\"count\" : 0,\n\t\t\t\t\"memory_in_bytes\" : 0,\n\t\t\t\t\"terms_memory_in_bytes\" : 0,\n\t\t\t\t\"stored_fields_memory_in_bytes\" : 0,\n\t\t\t\t\"term_vectors_memory_in_bytes\" : 0,\n\t\t\t\t\"norms_memory_in_bytes\" : 0,\n\t\t\t\t\"points_memory_in_bytes\" : 0,\n\t\t\t\t\"doc_values_memory_in_bytes\" : 0,\n\t\t\t\t\"index_writer_memory_in_bytes\" : 0,\n\t\t\t\t\"version_map_memory_in_bytes\" : 0,\n\t\t\t\t\"fixed_bit_set_memory_in_bytes\" : 0,\n\t\t\t\t\"max_unsafe_auto_id_timestamp\" : -9223372036854775808,\n\t\t\t\t\"file_sizes\" : { }\n\t\t\t  },\n\t\t\t  \"mappings\" : {\n\t\t\t\t\"field_types\" : [ ]\n\t\t\t  },\n\t\t\t  \"analysis\" : {\n\t\t\t\t\"char_filter_types\" : [ ],\n\t\t\t\t\"tokenizer_types\" : [ ],\n\t\t\t\t\"filter_types\" : [ ],\n\t\t\t\t\"analyzer_types\" : [ ],\n\t\t\t\t\"built_in_char_filters\" : [ ],\n\t\t\t\t\"built_in_tokenizers\" : [ ],\n\t\t\t\t\"built_in_filters\" : [ ],\n\t\t\t\t\"built_in_analyzers\" : [ ]\n\t\t\t  }\n\t\t\t},\n\t\t\t\"nodes\" : {\n\t\t\t  \"count\" : {\n\t\t\t\t\"total\" : 1,\n\t\t\t\t\"coordinating_only\" : 0,\n\t\t\t\t\"data\" : 1,\n\t\t\t\t\"data_cold\" : 1,\n\t\t\t\t\"data_content\" : 1,\n\t\t\t\t\"data_hot\" : 1,\n\t\t\t\t\"data_warm\" : 1,\n\t\t\t\t\"ingest\" : 1,\n\t\t\t\t\"master\" : 1,\n\t\t\t\t\"ml\" : 1,\n\t\t\t\t\"remote_cluster_client\" : 1,\n\t\t\t\t\"transform\" : 1,\n\t\t\t\t\"voting_only\" : 0\n\t\t\t  },\n\t\t\t  \"versions\" : [\n\t\t\t\t\"7.10.0\"\n\t\t\t  ],\n\t\t\t  \"os\" : {\n\t\t\t\t\"available_processors\" : 4,\n\t\t\t\t\"allocated_processors\" : 4,\n\t\t\t\t\"names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"name\" : \"Linux\",\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"pretty_names\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"pretty_name\" : \"CentOS Linux 8 (Core)\",\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"total_in_bytes\" : 8337850368,\n\t\t\t\t  \"free_in_bytes\" : 2907955200,\n\t\t\t\t  \"used_in_bytes\" : 5429895168,\n\t\t\t\t  \"free_percent\" : 35,\n\t\t\t\t  \"used_percent\" : 65\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"process\" : {\n\t\t\t\t\"cpu\" : {\n\t\t\t\t  \"percent\" : 0\n\t\t\t\t},\n\t\t\t\t\"open_file_descriptors\" : {\n\t\t\t\t  \"min\" : 253,\n\t\t\t\t  \"max\" : 253,\n\t\t\t\t  \"avg\" : 253\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"jvm\" : {\n\t\t\t\t\"max_uptime_in_millis\" : 59624,\n\t\t\t\t\"versions\" : [\n\t\t\t\t  {\n\t\t\t\t\t\"version\" : \"15.0.1\",\n\t\t\t\t\t\"vm_name\" : \"OpenJDK 64-Bit Server VM\",\n\t\t\t\t\t\"vm_version\" : \"15.0.1+9\",\n\t\t\t\t\t\"vm_vendor\" : \"AdoptOpenJDK\",\n\t\t\t\t\t\"bundled_jdk\" : true,\n\t\t\t\t\t\"using_bundled_jdk\" : true,\n\t\t\t\t\t\"count\" : 1\n\t\t\t\t  }\n\t\t\t\t],\n\t\t\t\t\"mem\" : {\n\t\t\t\t  \"heap_used_in_bytes\" : 308600832,\n\t\t\t\t  \"heap_max_in_bytes\" : 1073741824\n\t\t\t\t},\n\t\t\t\t\"threads\" : 35\n\t\t\t  },\n\t\t\t  \"fs\" : {\n\t\t\t\t\"total_in_bytes\" : 160377946112,\n\t\t\t\t\"free_in_bytes\" : 151653855232,\n\t\t\t\t\"available_in_bytes\" : 143476695040\n\t\t\t  },\n\t\t\t  \"plugins\" : [ ],\n\t\t\t  \"network_types\" : {\n\t\t\t\t\"transport_types\" : {\n\t\t\t\t  \"netty4\" : 1\n\t\t\t\t},\n\t\t\t\t\"http_types\" : {\n\t\t\t\t  \"netty4\" : 1\n\t\t\t\t}\n\t\t\t  },\n\t\t\t  \"discovery_types\" : {\n\t\t\t\t\"zen\" : 1\n\t\t\t  },\n\t\t\t  \"packaging_types\" : [\n\t\t\t\t{\n\t\t\t\t  \"flavor\" : \"default\",\n\t\t\t\t  \"type\" : \"docker\",\n\t\t\t\t  \"count\" : 1\n\t\t\t\t}\n\t\t\t  ],\n\t\t\t  \"ingest\" : {\n\t\t\t\t\"number_of_pipelines\" : 1,\n\t\t\t\t\"processor_stats\" : {\n\t\t\t\t  \"gsub\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  },\n\t\t\t\t  \"script\" : {\n\t\t\t\t\t\"count\" : 0,\n\t\t\t\t\t\"failed\" : 0,\n\t\t\t\t\t\"current\" : 0,\n\t\t\t\t\t\"time_in_millis\" : 0\n\t\t\t\t  }\n\t\t\t\t}\n\t\t\t  }\n\t\t\t}\n\t\t  }`,\n\t\tExpectedNodesStatsFailures: 2,\n\t},\n}\n\nfunc TestClusterStatsErrorResponse(t *testing.T) {\n\tfor i, tt := range clusterStatsErrorResponseTests {\n\t\tvar resp ClusterStatsResponse\n\t\tif err := json.Unmarshal([]byte(tt.Body), &resp); err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif want, have := tt.ExpectedNodesStatsFailures, len(resp.NodesStats.Failures); want != have {\n\t\t\tt.Fatalf(\"case #%d: expected %d errors, got %d\", i, want, have)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "config/config.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage config\n\nimport (\n\t\"fmt\"\n\t\"net/url\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Config represents an Elasticsearch configuration.\ntype Config struct {\n\tURL         string\n\tIndex       string\n\tUsername    string\n\tPassword    string\n\tShards      int\n\tReplicas    int\n\tSniff       *bool\n\tHealthcheck *bool\n\tInfolog     string\n\tErrorlog    string\n\tTracelog    string\n}\n\n// Parse returns the Elasticsearch configuration by extracting it\n// from the URL, its path, and its query string.\n//\n// Example:\n//   http://127.0.0.1:9200/store-blobs?shards=1&replicas=0&sniff=false&tracelog=elastic.trace.log\n//\n// The code above will return a URL of http://127.0.0.1:9200, an index name\n// of store-blobs, and the related settings from the query string.\nfunc Parse(elasticURL string) (*Config, error) {\n\tcfg := &Config{\n\t\tShards:   1,\n\t\tReplicas: 0,\n\t\tSniff:    nil,\n\t}\n\n\turi, err := url.Parse(elasticURL)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing elastic parameter %q: %v\", elasticURL, err)\n\t}\n\tindex := strings.TrimSuffix(strings.TrimPrefix(uri.Path, \"/\"), \"/\")\n\tif uri.User != nil {\n\t\tcfg.Username = uri.User.Username()\n\t\tcfg.Password, _ = uri.User.Password()\n\t}\n\turi.User = nil\n\n\tif i, err := strconv.Atoi(uri.Query().Get(\"shards\")); err == nil {\n\t\tcfg.Shards = i\n\t}\n\tif i, err := strconv.Atoi(uri.Query().Get(\"replicas\")); err == nil {\n\t\tcfg.Replicas = i\n\t}\n\tif s := uri.Query().Get(\"sniff\"); s != \"\" {\n\t\tif b, err := strconv.ParseBool(s); err == nil {\n\t\t\tcfg.Sniff = &b\n\t\t}\n\t}\n\tif s := uri.Query().Get(\"healthcheck\"); s != \"\" {\n\t\tif b, err := strconv.ParseBool(s); err == nil {\n\t\t\tcfg.Healthcheck = &b\n\t\t}\n\t}\n\tif s := uri.Query().Get(\"infolog\"); s != \"\" {\n\t\tcfg.Infolog = s\n\t}\n\tif s := uri.Query().Get(\"errorlog\"); s != \"\" {\n\t\tcfg.Errorlog = s\n\t}\n\tif s := uri.Query().Get(\"tracelog\"); s != \"\" {\n\t\tcfg.Tracelog = s\n\t}\n\n\turi.Path = \"\"\n\turi.RawQuery = \"\"\n\tcfg.URL = uri.String()\n\tcfg.Index = index\n\n\treturn cfg, nil\n}\n"
  },
  {
    "path": "config/config_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage config\n\nimport \"testing\"\n\nfunc TestParse(t *testing.T) {\n\turls := \"http://user:pwd@elastic:19220/store-blobs?shards=5&replicas=2&sniff=true&healthcheck=false&errorlog=elastic.error.log&infolog=elastic.info.log&tracelog=elastic.trace.log\"\n\tcfg, err := Parse(urls)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, got := \"http://elastic:19220\", cfg.URL; want != got {\n\t\tt.Fatalf(\"expected URL = %q, got %q\", want, got)\n\t}\n\tif want, got := \"store-blobs\", cfg.Index; want != got {\n\t\tt.Fatalf(\"expected Index = %q, got %q\", want, got)\n\t}\n\tif want, got := \"user\", cfg.Username; want != got {\n\t\tt.Fatalf(\"expected Username = %q, got %q\", want, got)\n\t}\n\tif want, got := \"pwd\", cfg.Password; want != got {\n\t\tt.Fatalf(\"expected Password = %q, got %q\", want, got)\n\t}\n\tif want, got := 5, cfg.Shards; want != got {\n\t\tt.Fatalf(\"expected Shards = %v, got %v\", want, got)\n\t}\n\tif want, got := 2, cfg.Replicas; want != got {\n\t\tt.Fatalf(\"expected Replicas = %v, got %v\", want, got)\n\t}\n\tif want, got := true, *cfg.Sniff; want != got {\n\t\tt.Fatalf(\"expected Sniff = %v, got %v\", want, got)\n\t}\n\tif want, got := false, *cfg.Healthcheck; want != got {\n\t\tt.Fatalf(\"expected Healthcheck = %v, got %v\", want, got)\n\t}\n\tif want, got := \"elastic.error.log\", cfg.Errorlog; want != got {\n\t\tt.Fatalf(\"expected Errorlog = %q, got %q\", want, got)\n\t}\n\tif want, got := \"elastic.info.log\", cfg.Infolog; want != got {\n\t\tt.Fatalf(\"expected Infolog = %q, got %q\", want, got)\n\t}\n\tif want, got := \"elastic.trace.log\", cfg.Tracelog; want != got {\n\t\tt.Fatalf(\"expected Tracelog = %q, got %q\", want, got)\n\t}\n}\n\nfunc TestParseDoesNotFailWithoutIndexName(t *testing.T) {\n\turls := \"http://user:pwd@elastic:19220/?shards=5&replicas=2&sniff=true&errorlog=elastic.error.log&infolog=elastic.info.log&tracelog=elastic.trace.log\"\n\tcfg, err := Parse(urls)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, got := \"http://elastic:19220\", cfg.URL; want != got {\n\t\tt.Fatalf(\"expected URL = %q, got %q\", want, got)\n\t}\n\tif want, got := \"\", cfg.Index; want != got {\n\t\tt.Fatalf(\"expected Index = %q, got %q\", want, got)\n\t}\n}\n\nfunc TestParseTrimsIndexName(t *testing.T) {\n\turls := \"http://user:pwd@elastic:19220/store-blobs/?sniff=true\"\n\tcfg, err := Parse(urls)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, got := \"http://elastic:19220\", cfg.URL; want != got {\n\t\tt.Fatalf(\"expected URL = %q, got %q\", want, got)\n\t}\n\tif want, got := \"store-blobs\", cfg.Index; want != got {\n\t\tt.Fatalf(\"expected Index = %q, got %q\", want, got)\n\t}\n}\n"
  },
  {
    "path": "config/doc.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n/*\nPackage config allows parsing a configuration for Elasticsearch\nfrom a URL.\n*/\npackage config\n"
  },
  {
    "path": "connection.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"fmt\"\n\t\"sync\"\n\t\"time\"\n)\n\n// conn represents a single connection to a node in a cluster.\ntype conn struct {\n\tsync.RWMutex\n\tnodeID    string // node ID\n\turl       string\n\tfailures  int\n\tdead      bool\n\tdeadSince *time.Time\n}\n\n// newConn creates a new connection to the given URL.\nfunc newConn(nodeID, url string) *conn {\n\tc := &conn{\n\t\tnodeID: nodeID,\n\t\turl:    url,\n\t}\n\treturn c\n}\n\n// String returns a representation of the connection status.\nfunc (c *conn) String() string {\n\tc.RLock()\n\tdefer c.RUnlock()\n\treturn fmt.Sprintf(\"%s [dead=%v,failures=%d,deadSince=%v]\", c.url, c.dead, c.failures, c.deadSince)\n}\n\n// NodeID returns the ID of the node of this connection.\nfunc (c *conn) NodeID() string {\n\tc.RLock()\n\tdefer c.RUnlock()\n\treturn c.nodeID\n}\n\n// URL returns the URL of this connection.\nfunc (c *conn) URL() string {\n\tc.RLock()\n\tdefer c.RUnlock()\n\treturn c.url\n}\n\n// IsDead returns true if this connection is marked as dead, i.e. a previous\n// request to the URL has been unsuccessful.\nfunc (c *conn) IsDead() bool {\n\tc.RLock()\n\tdefer c.RUnlock()\n\treturn c.dead\n}\n\n// MarkAsDead marks this connection as dead, increments the failures\n// counter and stores the current time in dead since.\nfunc (c *conn) MarkAsDead() {\n\tc.Lock()\n\tc.dead = true\n\tif c.deadSince == nil {\n\t\tutcNow := time.Now().UTC()\n\t\tc.deadSince = &utcNow\n\t}\n\tc.failures += 1\n\tc.Unlock()\n}\n\n// MarkAsAlive marks this connection as eligible to be returned from the\n// pool of connections by the selector.\nfunc (c *conn) MarkAsAlive() {\n\tc.Lock()\n\tc.dead = false\n\tc.Unlock()\n}\n\n// MarkAsHealthy marks this connection as healthy, i.e. a request has been\n// successfully performed with it.\nfunc (c *conn) MarkAsHealthy() {\n\tc.Lock()\n\tc.dead = false\n\tc.deadSince = nil\n\tc.failures = 0\n\tc.Unlock()\n}\n"
  },
  {
    "path": "count.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// CountService is a convenient service for determining the\n// number of documents in an index. Use SearchService with\n// a SearchType of count for counting with queries etc.\ntype CountService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex                  []string\n\ttyp                    []string\n\tallowNoIndices         *bool\n\tanalyzeWildcard        *bool\n\tanalyzer               string\n\tdefaultOperator        string\n\tdf                     string\n\texpandWildcards        string\n\tignoreUnavailable      *bool\n\tignoreThrottled        *bool\n\tlenient                *bool\n\tlowercaseExpandedTerms *bool\n\tminScore               interface{}\n\tpreference             string\n\tq                      string\n\tquery                  Query\n\trouting                string\n\tterminateAfter         *int\n\tbodyJson               interface{}\n\tbodyString             string\n}\n\n// NewCountService creates a new CountService.\nfunc NewCountService(client *Client) *CountService {\n\treturn &CountService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *CountService) Pretty(pretty bool) *CountService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *CountService) Human(human bool) *CountService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *CountService) ErrorTrace(errorTrace bool) *CountService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *CountService) FilterPath(filterPath ...string) *CountService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *CountService) Header(name string, value string) *CountService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *CountService) Headers(headers http.Header) *CountService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index sets the names of the indices to restrict the results.\nfunc (s *CountService) Index(index ...string) *CountService {\n\tif s.index == nil {\n\t\ts.index = make([]string, 0)\n\t}\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// Type sets the types to use to restrict the results.\n//\n// Deprecated: Types are in the process of being removed. Instead of using a type, prefer to\n// filter on a field on the document.\nfunc (s *CountService) Type(typ ...string) *CountService {\n\tif s.typ == nil {\n\t\ts.typ = make([]string, 0)\n\t}\n\ts.typ = append(s.typ, typ...)\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes \"_all\" string\n// or when no indices have been specified).\nfunc (s *CountService) AllowNoIndices(allowNoIndices bool) *CountService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// AnalyzeWildcard specifies whether wildcard and prefix queries should be\n// analyzed (default: false).\nfunc (s *CountService) AnalyzeWildcard(analyzeWildcard bool) *CountService {\n\ts.analyzeWildcard = &analyzeWildcard\n\treturn s\n}\n\n// Analyzer specifies the analyzer to use for the query string.\nfunc (s *CountService) Analyzer(analyzer string) *CountService {\n\ts.analyzer = analyzer\n\treturn s\n}\n\n// DefaultOperator specifies the default operator for query string query (AND or OR).\nfunc (s *CountService) DefaultOperator(defaultOperator string) *CountService {\n\ts.defaultOperator = defaultOperator\n\treturn s\n}\n\n// Df specifies the field to use as default where no field prefix is given\n// in the query string.\nfunc (s *CountService) Df(df string) *CountService {\n\ts.df = df\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *CountService) ExpandWildcards(expandWildcards string) *CountService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *CountService) IgnoreUnavailable(ignoreUnavailable bool) *CountService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// IgnoreThrottled indicates whether specified concrete, expanded or aliased\n// indices should be ignored when throttled.\nfunc (s *CountService) IgnoreThrottled(ignoreThrottled bool) *CountService {\n\ts.ignoreThrottled = &ignoreThrottled\n\treturn s\n}\n\n// Lenient specifies whether format-based query failures (such as\n// providing text to a numeric field) should be ignored.\nfunc (s *CountService) Lenient(lenient bool) *CountService {\n\ts.lenient = &lenient\n\treturn s\n}\n\n// LowercaseExpandedTerms specifies whether query terms should be lowercased.\nfunc (s *CountService) LowercaseExpandedTerms(lowercaseExpandedTerms bool) *CountService {\n\ts.lowercaseExpandedTerms = &lowercaseExpandedTerms\n\treturn s\n}\n\n// MinScore indicates to include only documents with a specific `_score`\n// value in the result.\nfunc (s *CountService) MinScore(minScore interface{}) *CountService {\n\ts.minScore = minScore\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be\n// performed on (default: random).\nfunc (s *CountService) Preference(preference string) *CountService {\n\ts.preference = preference\n\treturn s\n}\n\n// Q in the Lucene query string syntax. You can also use Query to pass\n// a Query struct.\nfunc (s *CountService) Q(q string) *CountService {\n\ts.q = q\n\treturn s\n}\n\n// Query specifies the query to pass. You can also pass a query string with Q.\nfunc (s *CountService) Query(query Query) *CountService {\n\ts.query = query\n\treturn s\n}\n\n// Routing specifies the routing value.\nfunc (s *CountService) Routing(routing string) *CountService {\n\ts.routing = routing\n\treturn s\n}\n\n// TerminateAfter indicates the maximum count for each shard, upon reaching\n// which the query execution will terminate early.\nfunc (s *CountService) TerminateAfter(terminateAfter int) *CountService {\n\ts.terminateAfter = &terminateAfter\n\treturn s\n}\n\n// BodyJson specifies the query to restrict the results specified with the\n// Query DSL (optional). The interface{} will be serialized to a JSON document,\n// so use a map[string]interface{}.\nfunc (s *CountService) BodyJson(body interface{}) *CountService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// Body specifies a query to restrict the results specified with\n// the Query DSL (optional).\nfunc (s *CountService) BodyString(body string) *CountService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *CountService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\tif len(s.index) > 0 && len(s.typ) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/_count\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t\t\"type\":  strings.Join(s.typ, \",\"),\n\t\t})\n\t} else if len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_count\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else if len(s.typ) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_all/{type}/_count\", map[string]string{\n\t\t\t\"type\": strings.Join(s.typ, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_all/_count\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.analyzeWildcard != nil {\n\t\tparams.Set(\"analyze_wildcard\", fmt.Sprintf(\"%v\", *s.analyzeWildcard))\n\t}\n\tif s.analyzer != \"\" {\n\t\tparams.Set(\"analyzer\", s.analyzer)\n\t}\n\tif s.defaultOperator != \"\" {\n\t\tparams.Set(\"default_operator\", s.defaultOperator)\n\t}\n\tif s.df != \"\" {\n\t\tparams.Set(\"df\", s.df)\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.ignoreThrottled != nil {\n\t\tparams.Set(\"ignore_throttled\", fmt.Sprintf(\"%v\", *s.ignoreThrottled))\n\t}\n\tif s.lenient != nil {\n\t\tparams.Set(\"lenient\", fmt.Sprintf(\"%v\", *s.lenient))\n\t}\n\tif s.lowercaseExpandedTerms != nil {\n\t\tparams.Set(\"lowercase_expanded_terms\", fmt.Sprintf(\"%v\", *s.lowercaseExpandedTerms))\n\t}\n\tif s.minScore != nil {\n\t\tparams.Set(\"min_score\", fmt.Sprintf(\"%v\", s.minScore))\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif s.q != \"\" {\n\t\tparams.Set(\"q\", s.q)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.terminateAfter != nil {\n\t\tparams.Set(\"terminate_after\", fmt.Sprintf(\"%v\", *s.terminateAfter))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *CountService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *CountService) Do(ctx context.Context) (int64, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn 0, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.query != nil {\n\t\tsrc, err := s.query.Source()\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\tquery := make(map[string]interface{})\n\t\tquery[\"query\"] = src\n\t\tbody = query\n\t} else if s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else if s.bodyString != \"\" {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\t// Return result\n\tret := new(CountResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn 0, err\n\t}\n\tif ret != nil {\n\t\treturn ret.Count, nil\n\t}\n\n\treturn int64(0), nil\n}\n\n// CountResponse is the response of using the Count API.\ntype CountResponse struct {\n\tCount           int64       `json:\"count\"`\n\tTerminatedEarly bool        `json:\"terminated_early,omitempty\"`\n\tShards          *ShardsInfo `json:\"_shards,omitempty\"`\n}\n"
  },
  {
    "path": "count_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestCountURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tTypes    []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"/_all/_count\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"tweet\"},\n\t\t\t\"/_all/tweet/_count\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"twitter-*\"},\n\t\t\t[]string{\"tweet\", \"follower\"},\n\t\t\t\"/twitter-%2A/tweet%2Cfollower/_count\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"twitter-2014\", \"twitter-2015\"},\n\t\t\t[]string{\"tweet\", \"follower\"},\n\t\t\t\"/twitter-2014%2Ctwitter-2015/tweet%2Cfollower/_count\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.Count().Index(test.Indices...).Type(test.Types...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestCount(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Count documents\n\tcount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 3 {\n\t\tt.Errorf(\"expected Count = %d; got %d\", 3, count)\n\t}\n\n\t// Count documents\n\tcount, err = client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 3 {\n\t\tt.Errorf(\"expected Count = %d; got %d\", 3, count)\n\t}\n\n\t// Count documents\n\tcount, err = client.Count(testIndexNameEmpty).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 0 {\n\t\tt.Errorf(\"expected Count = %d; got %d\", 0, count)\n\t}\n\n\t// Count with query\n\tquery := NewTermQuery(\"user\", \"olivere\")\n\tcount, err = client.Count(testIndexName).Query(query).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 2 {\n\t\tt.Errorf(\"expected Count = %d; got %d\", 2, count)\n\t}\n}\n"
  },
  {
    "path": "decoder.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n)\n\n// Decoder is used to decode responses from Elasticsearch.\n// Users of elastic can implement their own marshaler for advanced purposes\n// and set them per Client (see SetDecoder). If none is specified,\n// DefaultDecoder is used.\ntype Decoder interface {\n\tDecode(data []byte, v interface{}) error\n}\n\n// DefaultDecoder uses json.Unmarshal from the Go standard library\n// to decode JSON data.\ntype DefaultDecoder struct{}\n\n// Decode decodes with json.Unmarshal from the Go standard library.\nfunc (u *DefaultDecoder) Decode(data []byte, v interface{}) error {\n\treturn json.Unmarshal(data, v)\n}\n\n// NumberDecoder uses json.NewDecoder, with UseNumber() enabled, from\n// the Go standard library to decode JSON data.\ntype NumberDecoder struct{}\n\n// Decode decodes with json.Unmarshal from the Go standard library.\nfunc (u *NumberDecoder) Decode(data []byte, v interface{}) error {\n\tdec := json.NewDecoder(bytes.NewReader(data))\n\tdec.UseNumber()\n\treturn dec.Decode(v)\n}\n"
  },
  {
    "path": "decoder_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"sync/atomic\"\n\t\"testing\"\n)\n\ntype decoder struct {\n\tN int64\n}\n\nfunc (d *decoder) Decode(data []byte, v interface{}) error {\n\tatomic.AddInt64(&d.N, 1)\n\tdec := json.NewDecoder(bytes.NewReader(data))\n\tdec.UseNumber()\n\treturn dec.Decode(v)\n}\n\nfunc TestDecoder(t *testing.T) {\n\tdec := &decoder{}\n\tclient := setupTestClientAndCreateIndex(t, SetDecoder(dec), SetMaxRetries(0))\n\n\ttweet := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\n\t// Add a document\n\tindexResult, err := client.Index().\n\t\tIndex(testIndexName).\n\t\tId(\"1\").\n\t\tBodyJson(&tweet).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indexResult == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", indexResult)\n\t}\n\tif dec.N == 0 {\n\t\tt.Errorf(\"expected at least 1 call of decoder; got: %d\", dec.N)\n\t}\n}\n"
  },
  {
    "path": "delete.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// DeleteService allows to delete a typed JSON document from a specified\n// index based on its id.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-delete.html\n// for details.\ntype DeleteService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid                  string\n\tindex               string\n\ttyp                 string\n\trouting             string\n\ttimeout             string\n\tversion             interface{}\n\tversionType         string\n\twaitForActiveShards string\n\tparent              string\n\trefresh             string\n\tifSeqNo             *int64\n\tifPrimaryTerm       *int64\n}\n\n// NewDeleteService creates a new DeleteService.\nfunc NewDeleteService(client *Client) *DeleteService {\n\treturn &DeleteService{\n\t\tclient: client,\n\t\ttyp:    \"_doc\",\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *DeleteService) Pretty(pretty bool) *DeleteService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *DeleteService) Human(human bool) *DeleteService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *DeleteService) ErrorTrace(errorTrace bool) *DeleteService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *DeleteService) FilterPath(filterPath ...string) *DeleteService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *DeleteService) Header(name string, value string) *DeleteService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *DeleteService) Headers(headers http.Header) *DeleteService {\n\ts.headers = headers\n\treturn s\n}\n\n// Type is the type of the document.\n//\n// Deprecated: Types are in the process of being removed.\nfunc (s *DeleteService) Type(typ string) *DeleteService {\n\ts.typ = typ\n\treturn s\n}\n\n// Id is the document ID.\nfunc (s *DeleteService) Id(id string) *DeleteService {\n\ts.id = id\n\treturn s\n}\n\n// Index is the name of the index.\nfunc (s *DeleteService) Index(index string) *DeleteService {\n\ts.index = index\n\treturn s\n}\n\n// Routing is a specific routing value.\nfunc (s *DeleteService) Routing(routing string) *DeleteService {\n\ts.routing = routing\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *DeleteService) Timeout(timeout string) *DeleteService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// Version is an explicit version number for concurrency control.\nfunc (s *DeleteService) Version(version interface{}) *DeleteService {\n\ts.version = version\n\treturn s\n}\n\n// VersionType is a specific version type.\nfunc (s *DeleteService) VersionType(versionType string) *DeleteService {\n\ts.versionType = versionType\n\treturn s\n}\n\n// WaitForActiveShards sets the number of shard copies that must be active\n// before proceeding with the delete operation. Defaults to 1, meaning the\n// primary shard only. Set to `all` for all shard copies, otherwise set to\n// any non-negative value less than or equal to the total number of copies\n// for the shard (number of replicas + 1).\nfunc (s *DeleteService) WaitForActiveShards(waitForActiveShards string) *DeleteService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// Parent is the ID of parent document.\nfunc (s *DeleteService) Parent(parent string) *DeleteService {\n\ts.parent = parent\n\treturn s\n}\n\n// Refresh the index after performing the operation.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *DeleteService) Refresh(refresh string) *DeleteService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// IfSeqNo indicates to only perform the delete operation if the last\n// operation that has changed the document has the specified sequence number.\nfunc (s *DeleteService) IfSeqNo(seqNo int64) *DeleteService {\n\ts.ifSeqNo = &seqNo\n\treturn s\n}\n\n// IfPrimaryTerm indicates to only perform the delete operation if the\n// last operation that has changed the document has the specified primary term.\nfunc (s *DeleteService) IfPrimaryTerm(primaryTerm int64) *DeleteService {\n\ts.ifPrimaryTerm = &primaryTerm\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *DeleteService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/{type}/{id}\", map[string]string{\n\t\t\"index\": s.index,\n\t\t\"type\":  s.typ,\n\t\t\"id\":    s.id,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Set(\"refresh\", s.refresh)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif v := s.version; v != nil {\n\t\tparams.Set(\"version\", fmt.Sprint(v))\n\t}\n\tif s.versionType != \"\" {\n\t\tparams.Set(\"version_type\", s.versionType)\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\tif s.parent != \"\" {\n\t\tparams.Set(\"parent\", s.parent)\n\t}\n\tif v := s.ifSeqNo; v != nil {\n\t\tparams.Set(\"if_seq_no\", fmt.Sprintf(\"%d\", *v))\n\t}\n\tif v := s.ifPrimaryTerm; v != nil {\n\t\tparams.Set(\"if_primary_term\", fmt.Sprintf(\"%d\", *v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *DeleteService) Validate() error {\n\tvar invalid []string\n\tif s.typ == \"\" {\n\t\tinvalid = append(invalid, \"Type\")\n\t}\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation. If the document is not found (404), Elasticsearch will\n// still return a response. This response is serialized and returned as well. In other\n// words, for HTTP status code 404, both an error and a response might be returned.\nfunc (s *DeleteService) Do(ctx context.Context) (*DeleteResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:       \"DELETE\",\n\t\tPath:         path,\n\t\tParams:       params,\n\t\tIgnoreErrors: []int{http.StatusNotFound},\n\t\tHeaders:      s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(DeleteResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// If we have a 404, we return both a result and an error, just like ES does\n\tif res.StatusCode == http.StatusNotFound {\n\t\treturn ret, &Error{Status: http.StatusNotFound}\n\t}\n\n\treturn ret, nil\n}\n\n// -- Result of a delete request.\n\n// DeleteResponse is the outcome of running DeleteService.Do.\ntype DeleteResponse struct {\n\tIndex         string      `json:\"_index,omitempty\"`\n\tType          string      `json:\"_type,omitempty\"`\n\tId            string      `json:\"_id,omitempty\"`\n\tVersion       int64       `json:\"_version,omitempty\"`\n\tResult        string      `json:\"result,omitempty\"`\n\tShards        *ShardsInfo `json:\"_shards,omitempty\"`\n\tSeqNo         int64       `json:\"_seq_no,omitempty\"`\n\tPrimaryTerm   int64       `json:\"_primary_term,omitempty\"`\n\tStatus        int         `json:\"status,omitempty\"`\n\tForcedRefresh bool        `json:\"forced_refresh,omitempty\"`\n}\n"
  },
  {
    "path": "delete_by_query.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// DeleteByQueryService deletes documents that match a query.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-delete-by-query.html.\ntype DeleteByQueryService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex                  []string\n\ttyp                    []string\n\tquery                  Query\n\tbody                   interface{}\n\txSource                []string\n\txSourceExclude         []string\n\txSourceInclude         []string\n\tanalyzer               string\n\tanalyzeWildcard        *bool\n\tallowNoIndices         *bool\n\tconflicts              string\n\tdefaultOperator        string\n\tdf                     string\n\tdocvalueFields         []string\n\texpandWildcards        string\n\texplain                *bool\n\tfrom                   *int\n\tignoreUnavailable      *bool\n\tlenient                *bool\n\tlowercaseExpandedTerms *bool\n\tmaxDocs                *int\n\tpreference             string\n\tq                      string\n\trefresh                string\n\trequestCache           *bool\n\trequestsPerSecond      *int\n\trouting                []string\n\tscroll                 string\n\tscrollSize             *int\n\tsearchTimeout          string\n\tsearchType             string\n\tsize                   *int\n\tslices                 interface{}\n\tsort                   []string\n\tstats                  []string\n\tstoredFields           []string\n\tsuggestField           string\n\tsuggestMode            string\n\tsuggestSize            *int\n\tsuggestText            string\n\tterminateAfter         *int\n\ttimeout                string\n\ttrackScores            *bool\n\tversion                *bool\n\twaitForActiveShards    string\n\twaitForCompletion      *bool\n}\n\n// NewDeleteByQueryService creates a new DeleteByQueryService.\n// You typically use the client's DeleteByQuery to get a reference to\n// the service.\nfunc NewDeleteByQueryService(client *Client) *DeleteByQueryService {\n\tbuilder := &DeleteByQueryService{\n\t\tclient: client,\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *DeleteByQueryService) Pretty(pretty bool) *DeleteByQueryService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *DeleteByQueryService) Human(human bool) *DeleteByQueryService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *DeleteByQueryService) ErrorTrace(errorTrace bool) *DeleteByQueryService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *DeleteByQueryService) FilterPath(filterPath ...string) *DeleteByQueryService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *DeleteByQueryService) Header(name string, value string) *DeleteByQueryService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *DeleteByQueryService) Headers(headers http.Header) *DeleteByQueryService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index sets the indices on which to perform the delete operation.\nfunc (s *DeleteByQueryService) Index(index ...string) *DeleteByQueryService {\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// Type limits the delete operation to the given types.\n//\n// Deprecated: Types are in the process of being removed. Instead of\n// using a type, prefer to filter on a field of the document.\nfunc (s *DeleteByQueryService) Type(typ ...string) *DeleteByQueryService {\n\ts.typ = append(s.typ, typ...)\n\treturn s\n}\n\n// XSource is true or false to return the _source field or not,\n// or a list of fields to return.\nfunc (s *DeleteByQueryService) XSource(xSource ...string) *DeleteByQueryService {\n\ts.xSource = append(s.xSource, xSource...)\n\treturn s\n}\n\n// XSourceExclude represents a list of fields to exclude from the returned _source field.\nfunc (s *DeleteByQueryService) XSourceExclude(xSourceExclude ...string) *DeleteByQueryService {\n\ts.xSourceExclude = append(s.xSourceExclude, xSourceExclude...)\n\treturn s\n}\n\n// XSourceInclude represents a list of fields to extract and return from the _source field.\nfunc (s *DeleteByQueryService) XSourceInclude(xSourceInclude ...string) *DeleteByQueryService {\n\ts.xSourceInclude = append(s.xSourceInclude, xSourceInclude...)\n\treturn s\n}\n\n// Analyzer to use for the query string.\nfunc (s *DeleteByQueryService) Analyzer(analyzer string) *DeleteByQueryService {\n\ts.analyzer = analyzer\n\treturn s\n}\n\n// AnalyzeWildcard specifies whether wildcard and prefix queries should be\n// analyzed (default: false).\nfunc (s *DeleteByQueryService) AnalyzeWildcard(analyzeWildcard bool) *DeleteByQueryService {\n\ts.analyzeWildcard = &analyzeWildcard\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices (including the _all string\n// or when no indices have been specified).\nfunc (s *DeleteByQueryService) AllowNoIndices(allow bool) *DeleteByQueryService {\n\ts.allowNoIndices = &allow\n\treturn s\n}\n\n// Conflicts indicates what to do when the process detects version conflicts.\n// Possible values are \"proceed\" and \"abort\".\nfunc (s *DeleteByQueryService) Conflicts(conflicts string) *DeleteByQueryService {\n\ts.conflicts = conflicts\n\treturn s\n}\n\n// AbortOnVersionConflict aborts the request on version conflicts.\n// It is an alias to setting Conflicts(\"abort\").\nfunc (s *DeleteByQueryService) AbortOnVersionConflict() *DeleteByQueryService {\n\ts.conflicts = \"abort\"\n\treturn s\n}\n\n// ProceedOnVersionConflict proceeds the request on version conflicts.\n// It is an alias to setting Conflicts(\"proceed\").\nfunc (s *DeleteByQueryService) ProceedOnVersionConflict() *DeleteByQueryService {\n\ts.conflicts = \"proceed\"\n\treturn s\n}\n\n// DefaultOperator for query string query (AND or OR).\nfunc (s *DeleteByQueryService) DefaultOperator(defaultOperator string) *DeleteByQueryService {\n\ts.defaultOperator = defaultOperator\n\treturn s\n}\n\n// DF is the field to use as default where no field prefix is given in the query string.\nfunc (s *DeleteByQueryService) DF(defaultField string) *DeleteByQueryService {\n\ts.df = defaultField\n\treturn s\n}\n\n// DefaultField is the field to use as default where no field prefix is given in the query string.\n// It is an alias to the DF func.\nfunc (s *DeleteByQueryService) DefaultField(defaultField string) *DeleteByQueryService {\n\ts.df = defaultField\n\treturn s\n}\n\n// DocvalueFields specifies the list of fields to return as the docvalue representation of a field for each hit.\nfunc (s *DeleteByQueryService) DocvalueFields(docvalueFields ...string) *DeleteByQueryService {\n\ts.docvalueFields = docvalueFields\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both. It can be \"open\" or \"closed\".\nfunc (s *DeleteByQueryService) ExpandWildcards(expand string) *DeleteByQueryService {\n\ts.expandWildcards = expand\n\treturn s\n}\n\n// Explain specifies whether to return detailed information about score\n// computation as part of a hit.\nfunc (s *DeleteByQueryService) Explain(explain bool) *DeleteByQueryService {\n\ts.explain = &explain\n\treturn s\n}\n\n// From is the starting offset (default: 0).\nfunc (s *DeleteByQueryService) From(from int) *DeleteByQueryService {\n\ts.from = &from\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *DeleteByQueryService) IgnoreUnavailable(ignore bool) *DeleteByQueryService {\n\ts.ignoreUnavailable = &ignore\n\treturn s\n}\n\n// Lenient specifies whether format-based query failures\n// (such as providing text to a numeric field) should be ignored.\nfunc (s *DeleteByQueryService) Lenient(lenient bool) *DeleteByQueryService {\n\ts.lenient = &lenient\n\treturn s\n}\n\n// LowercaseExpandedTerms specifies whether query terms should be lowercased.\nfunc (s *DeleteByQueryService) LowercaseExpandedTerms(lowercaseExpandedTerms bool) *DeleteByQueryService {\n\ts.lowercaseExpandedTerms = &lowercaseExpandedTerms\n\treturn s\n}\n\n// MaxDocs specifies the maximum number of documents to process.\n// Defaults to all documents.\nfunc (s *DeleteByQueryService) MaxDocs(maxDocs int) *DeleteByQueryService {\n\ts.maxDocs = &maxDocs\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be performed on\n// (default: random).\nfunc (s *DeleteByQueryService) Preference(preference string) *DeleteByQueryService {\n\ts.preference = preference\n\treturn s\n}\n\n// Q specifies the query in Lucene query string syntax. You can also use\n// Query to programmatically specify the query.\nfunc (s *DeleteByQueryService) Q(query string) *DeleteByQueryService {\n\ts.q = query\n\treturn s\n}\n\n// QueryString is an alias to Q. Notice that you can also use Query to\n// programmatically set the query.\nfunc (s *DeleteByQueryService) QueryString(query string) *DeleteByQueryService {\n\ts.q = query\n\treturn s\n}\n\n// Query sets the query programmatically.\nfunc (s *DeleteByQueryService) Query(query Query) *DeleteByQueryService {\n\ts.query = query\n\treturn s\n}\n\n// Refresh indicates whether the effected indexes should be refreshed.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *DeleteByQueryService) Refresh(refresh string) *DeleteByQueryService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// RequestCache specifies if request cache should be used for this request\n// or not, defaults to index level setting.\nfunc (s *DeleteByQueryService) RequestCache(requestCache bool) *DeleteByQueryService {\n\ts.requestCache = &requestCache\n\treturn s\n}\n\n// RequestsPerSecond sets the throttle on this request in sub-requests per second.\n// -1 means set no throttle as does \"unlimited\" which is the only non-float this accepts.\nfunc (s *DeleteByQueryService) RequestsPerSecond(requestsPerSecond int) *DeleteByQueryService {\n\ts.requestsPerSecond = &requestsPerSecond\n\treturn s\n}\n\n// Routing is a list of specific routing values.\nfunc (s *DeleteByQueryService) Routing(routing ...string) *DeleteByQueryService {\n\ts.routing = append(s.routing, routing...)\n\treturn s\n}\n\n// Scroll specifies how long a consistent view of the index should be maintained\n// for scrolled search.\nfunc (s *DeleteByQueryService) Scroll(scroll string) *DeleteByQueryService {\n\ts.scroll = scroll\n\treturn s\n}\n\n// ScrollSize is the size on the scroll request powering the update_by_query.\nfunc (s *DeleteByQueryService) ScrollSize(scrollSize int) *DeleteByQueryService {\n\ts.scrollSize = &scrollSize\n\treturn s\n}\n\n// SearchTimeout defines an explicit timeout for each search request.\n// Defaults to no timeout.\nfunc (s *DeleteByQueryService) SearchTimeout(searchTimeout string) *DeleteByQueryService {\n\ts.searchTimeout = searchTimeout\n\treturn s\n}\n\n// SearchType is the search operation type. Possible values are\n// \"query_then_fetch\" and \"dfs_query_then_fetch\".\nfunc (s *DeleteByQueryService) SearchType(searchType string) *DeleteByQueryService {\n\ts.searchType = searchType\n\treturn s\n}\n\n// Size represents the number of hits to return (default: 10).\nfunc (s *DeleteByQueryService) Size(size int) *DeleteByQueryService {\n\ts.size = &size\n\treturn s\n}\n\n// Slices represents the number of slices (default: 1).\n// It used to  be a number, but can be set to \"auto\" as of 6.7.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-delete-by-query.html#docs-delete-by-query-automatic-slice\n// for details.\nfunc (s *DeleteByQueryService) Slices(slices interface{}) *DeleteByQueryService {\n\ts.slices = slices\n\treturn s\n}\n\n// Sort is a list of <field>:<direction> pairs.\nfunc (s *DeleteByQueryService) Sort(sort ...string) *DeleteByQueryService {\n\ts.sort = append(s.sort, sort...)\n\treturn s\n}\n\n// SortByField adds a sort order.\nfunc (s *DeleteByQueryService) SortByField(field string, ascending bool) *DeleteByQueryService {\n\tif ascending {\n\t\ts.sort = append(s.sort, fmt.Sprintf(\"%s:asc\", field))\n\t} else {\n\t\ts.sort = append(s.sort, fmt.Sprintf(\"%s:desc\", field))\n\t}\n\treturn s\n}\n\n// Stats specifies specific tag(s) of the request for logging and statistical purposes.\nfunc (s *DeleteByQueryService) Stats(stats ...string) *DeleteByQueryService {\n\ts.stats = append(s.stats, stats...)\n\treturn s\n}\n\n// StoredFields specifies the list of stored fields to return as part of a hit.\nfunc (s *DeleteByQueryService) StoredFields(storedFields ...string) *DeleteByQueryService {\n\ts.storedFields = storedFields\n\treturn s\n}\n\n// SuggestField specifies which field to use for suggestions.\nfunc (s *DeleteByQueryService) SuggestField(suggestField string) *DeleteByQueryService {\n\ts.suggestField = suggestField\n\treturn s\n}\n\n// SuggestMode specifies the suggest mode. Possible values are\n// \"missing\", \"popular\", and \"always\".\nfunc (s *DeleteByQueryService) SuggestMode(suggestMode string) *DeleteByQueryService {\n\ts.suggestMode = suggestMode\n\treturn s\n}\n\n// SuggestSize specifies how many suggestions to return in response.\nfunc (s *DeleteByQueryService) SuggestSize(suggestSize int) *DeleteByQueryService {\n\ts.suggestSize = &suggestSize\n\treturn s\n}\n\n// SuggestText specifies the source text for which the suggestions should be returned.\nfunc (s *DeleteByQueryService) SuggestText(suggestText string) *DeleteByQueryService {\n\ts.suggestText = suggestText\n\treturn s\n}\n\n// TerminateAfter indicates the maximum number of documents to collect\n// for each shard, upon reaching which the query execution will terminate early.\nfunc (s *DeleteByQueryService) TerminateAfter(terminateAfter int) *DeleteByQueryService {\n\ts.terminateAfter = &terminateAfter\n\treturn s\n}\n\n// Timeout is the time each individual bulk request should wait for shards\n// that are unavailable.\nfunc (s *DeleteByQueryService) Timeout(timeout string) *DeleteByQueryService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// TimeoutInMillis sets the timeout in milliseconds.\nfunc (s *DeleteByQueryService) TimeoutInMillis(timeoutInMillis int) *DeleteByQueryService {\n\ts.timeout = fmt.Sprintf(\"%dms\", timeoutInMillis)\n\treturn s\n}\n\n// TrackScores indicates whether to calculate and return scores even if\n// they are not used for sorting.\nfunc (s *DeleteByQueryService) TrackScores(trackScores bool) *DeleteByQueryService {\n\ts.trackScores = &trackScores\n\treturn s\n}\n\n// Version specifies whether to return document version as part of a hit.\nfunc (s *DeleteByQueryService) Version(version bool) *DeleteByQueryService {\n\ts.version = &version\n\treturn s\n}\n\n// WaitForActiveShards sets the number of shard copies that must be active before proceeding\n// with the update by query operation. Defaults to 1, meaning the primary shard only.\n// Set to `all` for all shard copies, otherwise set to any non-negative value less than or equal\n// to the total number of copies for the shard (number of replicas + 1).\nfunc (s *DeleteByQueryService) WaitForActiveShards(waitForActiveShards string) *DeleteByQueryService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// WaitForCompletion indicates if the request should block until the reindex is complete.\nfunc (s *DeleteByQueryService) WaitForCompletion(waitForCompletion bool) *DeleteByQueryService {\n\ts.waitForCompletion = &waitForCompletion\n\treturn s\n}\n\n// Body specifies the body of the request. It overrides data being specified via SearchService.\nfunc (s *DeleteByQueryService) Body(body string) *DeleteByQueryService {\n\ts.body = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *DeleteByQueryService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.typ) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/_delete_by_query\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t\t\"type\":  strings.Join(s.typ, \",\"),\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_delete_by_query\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif len(s.xSource) > 0 {\n\t\tparams.Set(\"_source\", strings.Join(s.xSource, \",\"))\n\t}\n\tif len(s.xSourceExclude) > 0 {\n\t\tparams.Set(\"_source_excludes\", strings.Join(s.xSourceExclude, \",\"))\n\t}\n\tif len(s.xSourceInclude) > 0 {\n\t\tparams.Set(\"_source_includes\", strings.Join(s.xSourceInclude, \",\"))\n\t}\n\tif s.analyzer != \"\" {\n\t\tparams.Set(\"analyzer\", s.analyzer)\n\t}\n\tif s.analyzeWildcard != nil {\n\t\tparams.Set(\"analyze_wildcard\", fmt.Sprintf(\"%v\", *s.analyzeWildcard))\n\t}\n\tif s.defaultOperator != \"\" {\n\t\tparams.Set(\"default_operator\", s.defaultOperator)\n\t}\n\tif s.df != \"\" {\n\t\tparams.Set(\"df\", s.df)\n\t}\n\tif s.explain != nil {\n\t\tparams.Set(\"explain\", fmt.Sprintf(\"%v\", *s.explain))\n\t}\n\tif len(s.storedFields) > 0 {\n\t\tparams.Set(\"stored_fields\", strings.Join(s.storedFields, \",\"))\n\t}\n\tif len(s.docvalueFields) > 0 {\n\t\tparams.Set(\"docvalue_fields\", strings.Join(s.docvalueFields, \",\"))\n\t}\n\tif s.from != nil {\n\t\tparams.Set(\"from\", fmt.Sprintf(\"%d\", *s.from))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.conflicts != \"\" {\n\t\tparams.Set(\"conflicts\", s.conflicts)\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.lenient != nil {\n\t\tparams.Set(\"lenient\", fmt.Sprintf(\"%v\", *s.lenient))\n\t}\n\tif s.lowercaseExpandedTerms != nil {\n\t\tparams.Set(\"lowercase_expanded_terms\", fmt.Sprintf(\"%v\", *s.lowercaseExpandedTerms))\n\t}\n\tif s.maxDocs != nil {\n\t\tparams.Set(\"max_docs\", fmt.Sprint(*s.maxDocs))\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif s.q != \"\" {\n\t\tparams.Set(\"q\", s.q)\n\t}\n\tif len(s.routing) > 0 {\n\t\tparams.Set(\"routing\", strings.Join(s.routing, \",\"))\n\t}\n\tif s.scroll != \"\" {\n\t\tparams.Set(\"scroll\", s.scroll)\n\t}\n\tif s.searchType != \"\" {\n\t\tparams.Set(\"search_type\", s.searchType)\n\t}\n\tif s.searchTimeout != \"\" {\n\t\tparams.Set(\"search_timeout\", s.searchTimeout)\n\t}\n\tif s.size != nil {\n\t\tparams.Set(\"size\", fmt.Sprintf(\"%d\", *s.size))\n\t}\n\tif s.slices != nil {\n\t\tparams.Set(\"slices\", fmt.Sprintf(\"%v\", s.slices))\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"sort\", strings.Join(s.sort, \",\"))\n\t}\n\tif s.terminateAfter != nil {\n\t\tparams.Set(\"terminate_after\", fmt.Sprintf(\"%v\", *s.terminateAfter))\n\t}\n\tif len(s.stats) > 0 {\n\t\tparams.Set(\"stats\", strings.Join(s.stats, \",\"))\n\t}\n\tif s.suggestField != \"\" {\n\t\tparams.Set(\"suggest_field\", s.suggestField)\n\t}\n\tif s.suggestMode != \"\" {\n\t\tparams.Set(\"suggest_mode\", s.suggestMode)\n\t}\n\tif s.suggestSize != nil {\n\t\tparams.Set(\"suggest_size\", fmt.Sprintf(\"%v\", *s.suggestSize))\n\t}\n\tif s.suggestText != \"\" {\n\t\tparams.Set(\"suggest_text\", s.suggestText)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.trackScores != nil {\n\t\tparams.Set(\"track_scores\", fmt.Sprintf(\"%v\", *s.trackScores))\n\t}\n\tif s.version != nil {\n\t\tparams.Set(\"version\", fmt.Sprintf(\"%v\", *s.version))\n\t}\n\tif s.requestCache != nil {\n\t\tparams.Set(\"request_cache\", fmt.Sprintf(\"%v\", *s.requestCache))\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Set(\"refresh\", s.refresh)\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\tif s.scrollSize != nil {\n\t\tparams.Set(\"scroll_size\", fmt.Sprintf(\"%d\", *s.scrollSize))\n\t}\n\tif s.waitForCompletion != nil {\n\t\tparams.Set(\"wait_for_completion\", fmt.Sprintf(\"%v\", *s.waitForCompletion))\n\t}\n\tif s.requestsPerSecond != nil {\n\t\tparams.Set(\"requests_per_second\", fmt.Sprintf(\"%v\", *s.requestsPerSecond))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *DeleteByQueryService) Validate() error {\n\tvar invalid []string\n\tif len(s.index) == 0 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the delete-by-query operation.\nfunc (s *DeleteByQueryService) Do(ctx context.Context) (*BulkIndexByScrollResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Set body if there is a query set\n\tvar body interface{}\n\tif s.body != nil {\n\t\tbody = s.body\n\t} else if s.query != nil {\n\t\tsrc, err := s.query.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbody = map[string]interface{}{\n\t\t\t\"query\": src,\n\t\t}\n\t}\n\n\t// Get response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return result\n\tret := new(BulkIndexByScrollResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// DoAsync executes the delete-by-query operation asynchronously by starting a new task.\n// Callers need to use the Task Management API to watch the outcome of the reindexing\n// operation.\nfunc (s *DeleteByQueryService) DoAsync(ctx context.Context) (*StartTaskResult, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// DoAsync only makes sense with WaitForCompletion set to true\n\tif s.waitForCompletion != nil && *s.waitForCompletion {\n\t\treturn nil, fmt.Errorf(\"cannot start a task with WaitForCompletion set to true\")\n\t}\n\tf := false\n\ts.waitForCompletion = &f\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Set body if there is a query set\n\tvar body interface{}\n\tif s.body != nil {\n\t\tbody = s.body\n\t} else if s.query != nil {\n\t\tsrc, err := s.query.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbody = map[string]interface{}{\n\t\t\t\"query\": src,\n\t\t}\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod: \"POST\",\n\t\tPath:   path,\n\t\tParams: params,\n\t\tBody:   body,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(StartTaskResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// BulkIndexByScrollResponse is the outcome of executing Do with\n// DeleteByQueryService and UpdateByQueryService.\ntype BulkIndexByScrollResponse struct {\n\tHeader           http.Header `json:\"-\"`\n\tTook             int64       `json:\"took\"`\n\tSliceId          *int64      `json:\"slice_id,omitempty\"`\n\tTimedOut         bool        `json:\"timed_out\"`\n\tTotal            int64       `json:\"total\"`\n\tUpdated          int64       `json:\"updated,omitempty\"`\n\tCreated          int64       `json:\"created,omitempty\"`\n\tDeleted          int64       `json:\"deleted\"`\n\tBatches          int64       `json:\"batches\"`\n\tVersionConflicts int64       `json:\"version_conflicts\"`\n\tNoops            int64       `json:\"noops\"`\n\tRetries          struct {\n\t\tBulk   int64 `json:\"bulk\"`\n\t\tSearch int64 `json:\"search\"`\n\t} `json:\"retries,omitempty\"`\n\tThrottled            string                             `json:\"throttled\"`\n\tThrottledMillis      int64                              `json:\"throttled_millis\"`\n\tRequestsPerSecond    float64                            `json:\"requests_per_second\"`\n\tCanceled             string                             `json:\"canceled,omitempty\"`\n\tThrottledUntil       string                             `json:\"throttled_until\"`\n\tThrottledUntilMillis int64                              `json:\"throttled_until_millis\"`\n\tFailures             []bulkIndexByScrollResponseFailure `json:\"failures\"`\n}\n\ntype bulkIndexByScrollResponseFailure struct {\n\tIndex  string `json:\"index,omitempty\"`\n\tType   string `json:\"type,omitempty\"`\n\tId     string `json:\"id,omitempty\"`\n\tStatus int    `json:\"status,omitempty\"`\n\tShard  int    `json:\"shard,omitempty\"`\n\tNode   int    `json:\"node,omitempty\"`\n\t// TODO \"cause\" contains exception details\n\t// TODO \"reason\" contains exception details\n}\n"
  },
  {
    "path": "delete_by_query_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestDeleteByQueryBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndices   []string\n\t\tTypes     []string\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{},\n\t\t\t\"/index1/_delete_by_query\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{},\n\t\t\t\"/index1%2Cindex2/_delete_by_query\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"type1\"},\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{\"type1\"},\n\t\t\t\"/index1/type1/_delete_by_query\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{\"type1\", \"type2\"},\n\t\t\t\"/index1%2Cindex2/type1%2Ctype2/_delete_by_query\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.DeleteByQuery().Index(test.Indices...).Type(test.Types...)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestDeleteByQuery(t *testing.T) {\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Count documents\n\tcount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 3 {\n\t\tt.Fatalf(\"expected count = %d; got: %d\", 3, count)\n\t}\n\n\t// Delete all documents by sandrae\n\tq := NewTermQuery(\"user\", \"sandrae\")\n\tres, err := client.DeleteByQuery().\n\t\tIndex(testIndexName).\n\t\tQuery(q).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected response != nil; got: %v\", res)\n\t}\n\n\t// Refresh and check count\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcount, err = client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 2 {\n\t\tt.Fatalf(\"expected Count = %d; got: %d\", 2, count)\n\t}\n}\n\nfunc TestDeleteByQueryAsync(t *testing.T) {\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Count documents\n\tcount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 3 {\n\t\tt.Fatalf(\"expected count = %d; got: %d\", 3, count)\n\t}\n\n\t// Delete all documents by sandrae\n\tq := NewTermQuery(\"user\", \"sandrae\")\n\tres, err := client.DeleteByQuery().\n\t\tIndex(testIndexName).\n\t\tQuery(q).\n\t\tSlices(\"auto\").\n\t\tPretty(true).\n\t\tDoAsync(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected result != nil\")\n\t}\n\tif res.TaskId == \"\" {\n\t\tt.Errorf(\"expected a task id, got %+v\", res)\n\t}\n\n\ttasksGetTask := client.TasksGetTask()\n\ttaskStatus, err := tasksGetTask.TaskId(res.TaskId).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif taskStatus == nil {\n\t\tt.Fatal(\"expected task status result != nil\")\n\t}\n}\n"
  },
  {
    "path": "delete_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestDelete(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Count documents\n\tcount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 3 {\n\t\tt.Errorf(\"expected Count = %d; got %d\", 3, count)\n\t}\n\n\t// Delete document 1\n\tres, err := client.Delete().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := \"deleted\", res.Result; want != have {\n\t\tt.Errorf(\"expected Result = %q; got %q\", want, have)\n\t}\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tcount, err = client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 2 {\n\t\tt.Errorf(\"expected Count = %d; got %d\", 2, count)\n\t}\n\n\t// Delete non existent document 99\n\tres, err = client.Delete().Index(testIndexName).Id(\"99\").Refresh(\"true\").Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatal(\"expected error\")\n\t}\n\tif !IsNotFound(err) {\n\t\tt.Fatalf(\"expected 404, got: %v\", err)\n\t}\n\tif _, ok := err.(*Error); !ok {\n\t\tt.Fatalf(\"expected error type *Error, got: %T\", err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response\")\n\t}\n\tif have, want := res.Id, \"99\"; have != want {\n\t\tt.Errorf(\"expected _id = %q, got %q\", have, want)\n\t}\n\tif have, want := res.Index, testIndexName; have != want {\n\t\tt.Errorf(\"expected _index = %q, got %q\", have, want)\n\t}\n\tif have, want := res.Type, \"_doc\"; have != want {\n\t\tt.Errorf(\"expected _type = %q, got %q\", have, want)\n\t}\n\tif have, want := res.Result, \"not_found\"; have != want {\n\t\tt.Errorf(\"expected Result = %q, got %q\", have, want)\n\t}\n\n\tcount, err = client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 2 {\n\t\tt.Errorf(\"expected Count = %d; got %d\", 2, count)\n\t}\n}\n\nfunc TestDeleteValidate(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// No index name -> fail with error\n\tres, err := NewDeleteService(client).Id(\"1\").Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected Delete to fail without index name\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected result to be == nil; got: %v\", res)\n\t}\n\n\t// No id -> fail with error\n\tres, err = NewDeleteService(client).Index(testIndexName).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected Delete to fail without id\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected result to be == nil; got: %v\", res)\n\t}\n}\n\nfunc TestDeleteOptimistic(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tdoc, err := client.Get().\n\t\tIndex(testIndexName).Id(\"1\").\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif doc.SeqNo == nil {\n\t\tt.Fatal(\"expected seq_no != nil\")\n\t}\n\tif doc.PrimaryTerm == nil {\n\t\tt.Fatal(\"expected primary_term != nil\")\n\t}\n\n\t// Delete with seqNo != doc.SeqNo and primaryTerm != doc.PrimaryTerm\n\t_, err = client.Delete().\n\t\tIndex(testIndexName).Id(doc.Id).\n\t\tIfSeqNo(*doc.SeqNo + 1000).\n\t\tIfPrimaryTerm(*doc.PrimaryTerm + 1000).\n\t\tDo(context.Background())\n\tif err == nil {\n\t\tt.Fatal(\"expected error, got nil\")\n\t}\n\tif !IsConflict(err) {\n\t\tt.Fatalf(\"expected conflict error, got %v (%T)\", err, err)\n\t}\n\n\t// Update with seqNo == doc.SeqNo and primaryTerm == doc.PrimaryTerm\n\tres, err := client.Delete().\n\t\tIndex(testIndexName).Id(doc.Id).\n\t\tIfSeqNo(*doc.SeqNo).\n\t\tIfPrimaryTerm(*doc.PrimaryTerm).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response != nil\")\n\t}\n}\n"
  },
  {
    "path": "doc.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n/*\nPackage elastic provides an interface to the Elasticsearch server\n(https://www.elastic.co/products/elasticsearch).\n\nThe first thing you do is to create a Client. If you have Elasticsearch\ninstalled and running with its default settings\n(i.e. available at http://127.0.0.1:9200), all you need to do is:\n\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\t// Handle error\n\t}\n\nIf your Elasticsearch server is running on a different IP and/or port,\njust provide a URL to NewClient:\n\n  // Create a client and connect to http://192.168.2.10:9201\n  client, err := elastic.NewClient(elastic.SetURL(\"http://192.168.2.10:9201\"))\n  if err != nil {\n    // Handle error\n  }\n\nYou can pass many more configuration parameters to NewClient. Review the\ndocumentation of NewClient for more information.\n\nIf no Elasticsearch server is available, services will fail when creating\na new request and will return ErrNoClient.\n\nA Client provides services. The services usually come with a variety of\nmethods to prepare the query and a Do function to execute it against the\nElasticsearch REST interface and return a response. Here is an example\nof the IndexExists service that checks if a given index already exists.\n\n\texists, err := client.IndexExists(\"twitter\").Do(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t}\n\tif !exists {\n\t\t// Index does not exist yet.\n\t}\n\nLook up the documentation for Client to get an idea of the services provided\nand what kinds of responses you get when executing the Do function of a service.\nAlso see the wiki on Github for more details.\n\n*/\npackage elastic\n"
  },
  {
    "path": "docker-compose.cluster.yml",
    "content": "services:\n  es1:\n    image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION:-7.14.0}\n    hostname: es1\n    environment:\n      - bootstrap.memory_lock=true\n      - cluster.name=elasticsearch\n      - cluster.initial_master_nodes=es1\n      - discovery.seed_hosts=es1\n      - cluster.routing.allocation.disk.threshold_enabled=false\n      - node.name=es1\n      - logger.org.elasticsearch=warn\n      - xpack.security.enabled=false\n      - \"ES_JAVA_OPTS=-Xms1g -Xmx1g\"\n    ulimits:\n      nproc: 65536\n      nofile:\n        soft: 65536\n        hard: 65536\n      memlock:\n        soft: -1\n        hard: -1\n    # volumes:\n    #   - ./data/elasticsearch:/usr/share/elasticsearch/data\n    ports:\n      - 9200:9200\n\n  es2:\n    image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION:-7.14.0}\n    hostname: es2\n    environment:\n      - bootstrap.memory_lock=true\n      - cluster.name=elasticsearch\n      - cluster.initial_master_nodes=es1\n      - discovery.seed_hosts=es1\n      - cluster.routing.allocation.disk.threshold_enabled=false\n      - node.name=es2\n      - logger.org.elasticsearch=warn\n      - xpack.security.enabled=false\n      - \"ES_JAVA_OPTS=-Xms1g -Xmx1g\"\n    ulimits:\n      nproc: 65536\n      nofile:\n        soft: 65536\n        hard: 65536\n      memlock:\n        soft: -1\n        hard: -1\n    # volumes:\n    #   - ./data/elasticsearch:/usr/share/elasticsearch/data\n    ports:\n      - 9201:9200\n\n  es3:\n    image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION:-7.14.0}\n    hostname: es3\n    environment:\n      - bootstrap.memory_lock=true\n      - cluster.name=elasticsearch\n      - cluster.initial_master_nodes=es1\n      - discovery.seed_hosts=es1\n      - cluster.routing.allocation.disk.threshold_enabled=false\n      - node.name=es3\n      - logger.org.elasticsearch=warn\n      - xpack.security.enabled=false\n      - \"ES_JAVA_OPTS=-Xms1g -Xmx1g\"\n    ulimits:\n      nproc: 65536\n      nofile:\n        soft: 65536\n        hard: 65536\n      memlock:\n        soft: -1\n        hard: -1\n    # volumes:\n    #   - ./data/elasticsearch:/usr/share/elasticsearch/data\n    ports:\n      - 9202:9200\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "services:\n  elasticsearch:\n    image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION:-7.17.1}\n    hostname: elasticsearch\n    environment:\n      - cluster.name=elasticsearch\n      - bootstrap.memory_lock=true\n      - discovery.type=single-node\n      # - http.publish_host=localhost\n      # - http.host=0.0.0.0\n      # - transport.host=127.0.0.1\n      # - network.host=_local_\n      - network.publish_host=127.0.0.1\n      - logger.org.elasticsearch=warn\n      - xpack.security.enabled=false\n      - path.repo=/usr/share/elasticsearch/backup\n      - \"ES_JAVA_OPTS=-Xms1g -Xmx1g\"\n    ulimits:\n      nproc: 65536\n      nofile:\n        soft: 65536\n        hard: 65536\n      memlock:\n        soft: -1\n        hard: -1\n    volumes:\n      - ./data/backup:/usr/share/elasticsearch/backup\n    ports:\n      - 9200:9200\n  platinum:\n    image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION:-7.17.1}\n    hostname: elasticsearch-platinum\n    environment:\n      - cluster.name=platinum\n      - bootstrap.memory_lock=true\n      - discovery.type=single-node\n      - xpack.license.self_generated.type=trial\n      - xpack.security.enabled=true\n      - xpack.watcher.enabled=true\n      # - http.publish_host=localhost\n      # - http.host=0.0.0.0\n      # - transport.host=127.0.0.1\n      # - network.host=_local_\n      - http.port=9210\n      - network.publish_host=127.0.0.1\n      - logger.org.elasticsearch=warn\n      - path.repo=/usr/share/elasticsearch/backup\n      - \"ES_JAVA_OPTS=-Xms1g -Xmx1g\"\n      - ELASTIC_PASSWORD=elastic\n    ulimits:\n      nproc: 65536\n      nofile:\n        soft: 65536\n        hard: 65536\n      memlock:\n        soft: -1\n        hard: -1\n    volumes:\n      - ./data/backup:/usr/share/elasticsearch/backup\n    ports:\n      - 9210:9210\n"
  },
  {
    "path": "docvalue_field.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// DocvalueField represents a docvalue field, its name and\n// its format (optional).\ntype DocvalueField struct {\n\tField  string\n\tFormat string\n}\n\n// Source serializes the DocvalueField into JSON.\nfunc (d DocvalueField) Source() (interface{}, error) {\n\tif d.Format == \"\" {\n\t\treturn d.Field, nil\n\t}\n\treturn map[string]interface{}{\n\t\t\"field\":  d.Field,\n\t\t\"format\": d.Format,\n\t}, nil\n}\n\n// DocvalueFields is a slice of DocvalueField instances.\ntype DocvalueFields []DocvalueField\n\n// Source serializes the DocvalueFields into JSON.\nfunc (d DocvalueFields) Source() (interface{}, error) {\n\tif d == nil {\n\t\treturn nil, nil\n\t}\n\tv := make([]interface{}, 0)\n\tfor _, f := range d {\n\t\tsrc, err := f.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tv = append(v, src)\n\t}\n\treturn v, nil\n}\n"
  },
  {
    "path": "docvalue_field_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc TestDocvalueField(t *testing.T) {\n\ttests := []struct {\n\t\tDoc  DocvalueField\n\t\tWant interface{}\n\t}{\n\t\t{\n\t\t\tDoc:  DocvalueField{},\n\t\t\tWant: \"\",\n\t\t},\n\t\t{\n\t\t\tDoc:  DocvalueField{Field: \"name\"},\n\t\t\tWant: \"name\",\n\t\t},\n\t\t{\n\t\t\tDoc:  DocvalueField{Field: \"name\", Format: \"epoch_millis\"},\n\t\t\tWant: map[string]interface{}{\"field\": \"name\", \"format\": \"epoch_millis\"},\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\thave, err := tt.Doc.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"Source(%#v): err=%v\", tt.Doc, err)\n\t\t}\n\t\tif want := tt.Want; !cmp.Equal(want, have) {\n\t\t\tt.Fatalf(\"Source(%#v): want %v, have %v\", tt.Doc, want, have)\n\t\t}\n\t}\n}\n\nfunc TestDocvalueFields(t *testing.T) {\n\tdoc := DocvalueFields{\n\t\tDocvalueField{Field: \"retweets\"},\n\t\tDocvalueField{Field: \"name\", Format: \"epoch_millis\"},\n\t}\n\thave, err := doc.Source()\n\tif err != nil {\n\t\tt.Fatalf(\"Source(%#v): err=%v\", doc, err)\n\t}\n\twant := []interface{}{\n\t\t\"retweets\",\n\t\tmap[string]interface{}{\"field\": \"name\", \"format\": \"epoch_millis\"},\n\t}\n\tif !cmp.Equal(want, have) {\n\t\tt.Fatalf(\"Source(%#v): want %v, have %v\", doc, want, have)\n\t}\n}\n"
  },
  {
    "path": "errors.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/pkg/errors\"\n)\n\n// checkResponse will return an error if the request/response indicates\n// an error returned from Elasticsearch.\n//\n// HTTP status codes between in the range [200..299] are considered successful.\n// All other errors are considered errors except they are specified in\n// ignoreErrors. This is necessary because for some services, HTTP status 404\n// is a valid response from Elasticsearch (e.g. the Exists service).\n//\n// The func tries to parse error details as returned from Elasticsearch\n// and encapsulates them in type elastic.Error.\nfunc checkResponse(req *http.Request, res *http.Response, ignoreErrors ...int) error {\n\t// 200-299 are valid status codes\n\tif res.StatusCode >= 200 && res.StatusCode <= 299 {\n\t\treturn nil\n\t}\n\t// Ignore certain errors?\n\tfor _, code := range ignoreErrors {\n\t\tif code == res.StatusCode {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn createResponseError(res)\n}\n\n// createResponseError creates an Error structure from the HTTP response,\n// its status code and the error information sent by Elasticsearch.\nfunc createResponseError(res *http.Response) error {\n\tif res.Body == nil {\n\t\treturn &Error{Status: res.StatusCode}\n\t}\n\tdata, err := ioutil.ReadAll(res.Body)\n\tif err != nil {\n\t\treturn &Error{Status: res.StatusCode}\n\t}\n\terrReply := new(Error)\n\terr = json.Unmarshal(data, errReply)\n\tif err != nil {\n\t\treturn &Error{Status: res.StatusCode}\n\t}\n\tif errReply != nil {\n\t\tif errReply.Status == 0 {\n\t\t\terrReply.Status = res.StatusCode\n\t\t}\n\t\treturn errReply\n\t}\n\treturn &Error{Status: res.StatusCode}\n}\n\n// Error encapsulates error details as returned from Elasticsearch.\ntype Error struct {\n\tStatus  int           `json:\"status\"`\n\tDetails *ErrorDetails `json:\"error,omitempty\"`\n}\n\n// ErrorDetails encapsulate error details from Elasticsearch.\n// It is used in e.g. elastic.Error and elastic.BulkResponseItem.\ntype ErrorDetails struct {\n\tType         string                   `json:\"type\"`\n\tReason       string                   `json:\"reason\"`\n\tResourceType string                   `json:\"resource.type,omitempty\"`\n\tResourceId   string                   `json:\"resource.id,omitempty\"`\n\tIndex        string                   `json:\"index,omitempty\"`\n\tPhase        string                   `json:\"phase,omitempty\"`\n\tGrouped      bool                     `json:\"grouped,omitempty\"`\n\tCausedBy     map[string]interface{}   `json:\"caused_by,omitempty\"`\n\tRootCause    []*ErrorDetails          `json:\"root_cause,omitempty\"`\n\tSuppressed   []*ErrorDetails          `json:\"suppressed,omitempty\"`\n\tFailedShards []map[string]interface{} `json:\"failed_shards,omitempty\"`\n\tHeader       map[string]interface{}   `json:\"header,omitempty\"`\n\n\t// ScriptException adds the information in the following block.\n\n\tScriptStack []string             `json:\"script_stack,omitempty\"` // from ScriptException\n\tScript      string               `json:\"script,omitempty\"`       // from ScriptException\n\tLang        string               `json:\"lang,omitempty\"`         // from ScriptException\n\tPosition    *ScriptErrorPosition `json:\"position,omitempty\"`     // from ScriptException (7.7+)\n}\n\n// ScriptErrorPosition specifies the position of the error\n// in a script. It is used in ErrorDetails for scripting errors.\ntype ScriptErrorPosition struct {\n\tOffset int `json:\"offset\"`\n\tStart  int `json:\"start\"`\n\tEnd    int `json:\"end\"`\n}\n\n// Error returns a string representation of the error.\nfunc (e *Error) Error() string {\n\tif e.Details != nil && e.Details.Reason != \"\" {\n\t\treturn fmt.Sprintf(\"elastic: Error %d (%s): %s [type=%s]\", e.Status, http.StatusText(e.Status), e.Details.Reason, e.Details.Type)\n\t}\n\treturn fmt.Sprintf(\"elastic: Error %d (%s)\", e.Status, http.StatusText(e.Status))\n}\n\n// ErrorReason returns the reason of an error that Elasticsearch reported,\n// if err is of kind Error and has ErrorDetails with a Reason. Any other\n// value of err will return an empty string.\nfunc ErrorReason(err error) string {\n\tif err == nil {\n\t\treturn \"\"\n\t}\n\te, ok := err.(*Error)\n\tif !ok || e == nil || e.Details == nil {\n\t\treturn \"\"\n\t}\n\treturn e.Details.Reason\n}\n\n// IsContextErr returns true if the error is from a context that was canceled or deadline exceeded\nfunc IsContextErr(err error) bool {\n\tif err == context.Canceled || err == context.DeadlineExceeded {\n\t\treturn true\n\t}\n\t// This happens e.g. on redirect errors, see https://golang.org/src/net/http/client_test.go#L329\n\tif ue, ok := err.(*url.Error); ok {\n\t\tif ue.Temporary() {\n\t\t\treturn true\n\t\t}\n\t\t// Use of an AWS Signing Transport can result in a wrapped url.Error\n\t\treturn IsContextErr(ue.Err)\n\t}\n\treturn false\n}\n\n// IsConnErr returns true if the error indicates that Elastic could not\n// find an Elasticsearch host to connect to.\nfunc IsConnErr(err error) bool {\n\treturn err == ErrNoClient || errors.Cause(err) == ErrNoClient\n}\n\n// IsNotFound returns true if the given error indicates that Elasticsearch\n// returned HTTP status 404. The err parameter can be of type *elastic.Error,\n// elastic.Error, *http.Response or int (indicating the HTTP status code).\nfunc IsNotFound(err interface{}) bool {\n\treturn IsStatusCode(err, http.StatusNotFound)\n}\n\n// IsTimeout returns true if the given error indicates that Elasticsearch\n// returned HTTP status 408. The err parameter can be of type *elastic.Error,\n// elastic.Error, *http.Response or int (indicating the HTTP status code).\nfunc IsTimeout(err interface{}) bool {\n\treturn IsStatusCode(err, http.StatusRequestTimeout)\n}\n\n// IsConflict returns true if the given error indicates that the Elasticsearch\n// operation resulted in a version conflict. This can occur in operations like\n// `update` or `index` with `op_type=create`. The err parameter can be of\n// type *elastic.Error, elastic.Error, *http.Response or int (indicating the\n// HTTP status code).\nfunc IsConflict(err interface{}) bool {\n\treturn IsStatusCode(err, http.StatusConflict)\n}\n\n// IsUnauthorized returns true if the given error indicates that\n// Elasticsearch returned HTTP status 401. This happens e.g. when the\n// cluster is configured to require HTTP Basic Auth.\n// The err parameter can be of type *elastic.Error, elastic.Error,\n// *http.Response or int (indicating the HTTP status code).\nfunc IsUnauthorized(err interface{}) bool {\n\treturn IsStatusCode(err, http.StatusUnauthorized)\n}\n\n// IsForbidden returns true if the given error indicates that Elasticsearch\n// returned HTTP status 403. This happens e.g. due to a missing license.\n// The err parameter can be of type *elastic.Error, elastic.Error,\n// *http.Response or int (indicating the HTTP status code).\nfunc IsForbidden(err interface{}) bool {\n\treturn IsStatusCode(err, http.StatusForbidden)\n}\n\n// IsStatusCode returns true if the given error indicates that the Elasticsearch\n// operation returned the specified HTTP status code. The err parameter can be of\n// type *http.Response, *Error, Error, or int (indicating the HTTP status code).\nfunc IsStatusCode(err interface{}, code int) bool {\n\tswitch e := err.(type) {\n\tcase *http.Response:\n\t\treturn e.StatusCode == code\n\tcase *Error:\n\t\treturn e.Status == code\n\tcase Error:\n\t\treturn e.Status == code\n\tcase int:\n\t\treturn e == code\n\t}\n\treturn false\n}\n\n// -- General errors --\n\n// ShardsInfo represents information from a shard.\ntype ShardsInfo struct {\n\tTotal      int                              `json:\"total\"`\n\tSuccessful int                              `json:\"successful\"`\n\tFailed     int                              `json:\"failed\"`\n\tFailures   []*ShardOperationFailedException `json:\"failures,omitempty\"`\n\tSkipped    int                              `json:\"skipped,omitempty\"`\n}\n\ntype ShardOperationFailedException struct {\n\tShard  int                    `json:\"shard,omitempty\"`\n\tIndex  string                 `json:\"index,omitempty\"`\n\tStatus string                 `json:\"status,omitempty\"`\n\tReason map[string]interface{} `json:\"reason,omitempty\"`\n\n\t// TODO(oe) Do we still have those?\n\tNode string `json:\"_node,omitempty\"`\n\t// TODO(oe) Do we still have those?\n\tPrimary bool `json:\"primary,omitempty\"`\n}\n\ntype BroadcastResponse struct {\n\tShards     *ShardsInfo                      `json:\"_shards,omitempty\"`\n\tTotal      int                              `json:\"total\"`\n\tSuccessful int                              `json:\"successful\"`\n\tFailed     int                              `json:\"failed\"`\n\tFailures   []*ShardOperationFailedException `json:\"failures,omitempty\"`\n}\n\n// FailedNodeException returns an error on the node level.\ntype FailedNodeException struct {\n\t*ErrorDetails\n\tNodeId string `json:\"node_id\"`\n}\n"
  },
  {
    "path": "errors_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestErrorReason(t *testing.T) {\n\tif want, have := \"\", ErrorReason(nil); want != have {\n\t\tt.Fatalf(\"want %q, have %q\", want, have)\n\t}\n\n\tif want, have := \"\", ErrorReason(&Error{}); want != have {\n\t\tt.Fatalf(\"want %q, have %q\", want, have)\n\t}\n\n\tif want, have := \"\", ErrorReason(&Error{Details: &ErrorDetails{}}); want != have {\n\t\tt.Fatalf(\"want %q, have %q\", want, have)\n\t}\n\n\tif want, have := \"no such index\", ErrorReason(&Error{Details: &ErrorDetails{Reason: \"no such index\"}}); want != have {\n\t\tt.Fatalf(\"want %q, have %q\", want, have)\n\t}\n}\n\nfunc TestResponseError(t *testing.T) {\n\traw := \"HTTP/1.1 404 Not Found\\r\\n\" +\n\t\t\"\\r\\n\" +\n\t\t`{\"error\":{\"root_cause\":[{\"type\":\"index_missing_exception\",\"reason\":\"no such index\",\"index\":\"elastic-test\"}],\"type\":\"index_missing_exception\",\"reason\":\"no such index\",\"index\":\"elastic-test\"},\"status\":404}` + \"\\r\\n\"\n\tr := bufio.NewReader(strings.NewReader(raw))\n\n\treq, err := http.NewRequest(\"GET\", \"/\", nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tresp, err := http.ReadResponse(r, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\terr = checkResponse(req, resp)\n\tif err == nil {\n\t\tt.Fatalf(\"expected error; got: %v\", err)\n\t}\n\n\t// Check for correct error message\n\texpected := fmt.Sprintf(\"elastic: Error %d (%s): no such index [type=index_missing_exception]\", resp.StatusCode, http.StatusText(resp.StatusCode))\n\tgot := err.Error()\n\tif got != expected {\n\t\tt.Fatalf(\"expected %q; got: %q\", expected, got)\n\t}\n\n\t// Check ErrorReason\n\tif expected, got := \"no such index\", ErrorReason(err); expected != got {\n\t\tt.Fatalf(\"expected %q; got: %q\", expected, got)\n\t}\n\n\t// Check that error is of type *elastic.Error, which contains additional information\n\te, ok := err.(*Error)\n\tif !ok {\n\t\tt.Fatal(\"expected error to be of type *elastic.Error\")\n\t}\n\tif e.Status != resp.StatusCode {\n\t\tt.Fatalf(\"expected status code %d; got: %d\", resp.StatusCode, e.Status)\n\t}\n\tif e.Details == nil {\n\t\tt.Fatalf(\"expected error details; got: %v\", e.Details)\n\t}\n\tif got, want := e.Details.Index, \"elastic-test\"; got != want {\n\t\tt.Fatalf(\"expected error details index %q; got: %q\", want, got)\n\t}\n\tif got, want := e.Details.Type, \"index_missing_exception\"; got != want {\n\t\tt.Fatalf(\"expected error details type %q; got: %q\", want, got)\n\t}\n\tif got, want := e.Details.Reason, \"no such index\"; got != want {\n\t\tt.Fatalf(\"expected error details reason %q; got: %q\", want, got)\n\t}\n\tif got, want := len(e.Details.RootCause), 1; got != want {\n\t\tt.Fatalf(\"expected %d error details root causes; got: %d\", want, got)\n\t}\n\n\tif got, want := e.Details.RootCause[0].Index, \"elastic-test\"; got != want {\n\t\tt.Fatalf(\"expected root cause index %q; got: %q\", want, got)\n\t}\n\tif got, want := e.Details.RootCause[0].Type, \"index_missing_exception\"; got != want {\n\t\tt.Fatalf(\"expected root cause type %q; got: %q\", want, got)\n\t}\n\tif got, want := e.Details.RootCause[0].Reason, \"no such index\"; got != want {\n\t\tt.Fatalf(\"expected root cause reason %q; got: %q\", want, got)\n\t}\n}\n\nfunc TestResponseErrorHTML(t *testing.T) {\n\traw := \"HTTP/1.1 413 Request Entity Too Large\\r\\n\" +\n\t\t\"\\r\\n\" +\n\t\t`<html>\n<head><title>413 Request Entity Too Large</title></head>\n<body bgcolor=\"white\">\n<center><h1>413 Request Entity Too Large</h1></center>\n<hr><center>nginx/1.6.2</center>\n</body>\n</html>` + \"\\r\\n\"\n\tr := bufio.NewReader(strings.NewReader(raw))\n\n\treq, err := http.NewRequest(\"GET\", \"/\", nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tresp, err := http.ReadResponse(r, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\terr = checkResponse(req, resp)\n\tif err == nil {\n\t\tt.Fatalf(\"expected error; got: %v\", err)\n\t}\n\n\t// Check for correct error message\n\texpected := fmt.Sprintf(\"elastic: Error %d (%s)\", http.StatusRequestEntityTooLarge, http.StatusText(http.StatusRequestEntityTooLarge))\n\tgot := err.Error()\n\tif got != expected {\n\t\tt.Fatalf(\"expected %q; got: %q\", expected, got)\n\t}\n}\n\nfunc TestResponseErrorWithIgnore(t *testing.T) {\n\traw := \"HTTP/1.1 404 Not Found\\r\\n\" +\n\t\t\"\\r\\n\" +\n\t\t`{\"some\":\"response\"}` + \"\\r\\n\"\n\tr := bufio.NewReader(strings.NewReader(raw))\n\n\treq, err := http.NewRequest(\"HEAD\", \"/\", nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tresp, err := http.ReadResponse(r, nil)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\terr = checkResponse(req, resp)\n\tif err == nil {\n\t\tt.Fatalf(\"expected error; got: %v\", err)\n\t}\n\terr = checkResponse(req, resp, 404) // ignore 404 errors\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n}\n\nfunc TestIsNotFound(t *testing.T) {\n\tif got, want := IsNotFound(nil), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsNotFound(\"\"), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsNotFound(200), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsNotFound(404), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\n\tif got, want := IsNotFound(&Error{Status: 404}), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsNotFound(&Error{Status: 200}), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\n\tif got, want := IsNotFound(Error{Status: 404}), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsNotFound(Error{Status: 200}), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\n\tif got, want := IsNotFound(&http.Response{StatusCode: 404}), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsNotFound(&http.Response{StatusCode: 200}), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n}\n\nfunc TestIsTimeout(t *testing.T) {\n\tif got, want := IsTimeout(nil), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsTimeout(\"\"), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsTimeout(200), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsTimeout(408), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\n\tif got, want := IsTimeout(&Error{Status: 408}), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsTimeout(&Error{Status: 200}), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\n\tif got, want := IsTimeout(Error{Status: 408}), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsTimeout(Error{Status: 200}), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\n\tif got, want := IsTimeout(&http.Response{StatusCode: 408}), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsTimeout(&http.Response{StatusCode: 200}), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n}\n\nfunc TestIsConflict(t *testing.T) {\n\tif got, want := IsConflict(nil), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsConflict(\"\"), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsConflict(200), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsConflict(http.StatusConflict), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\n\tif got, want := IsConflict(&Error{Status: 409}), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsConflict(&Error{Status: 200}), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\n\tif got, want := IsConflict(Error{Status: 409}), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsConflict(Error{Status: 200}), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\n\tif got, want := IsConflict(&http.Response{StatusCode: 409}), true; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n\tif got, want := IsConflict(&http.Response{StatusCode: 200}), false; got != want {\n\t\tt.Errorf(\"expected %v; got: %v\", want, got)\n\t}\n}\n\nfunc TestIsStatusCode(t *testing.T) {\n\ttests := []struct {\n\t\tError interface{}\n\t\tCode  int\n\t\tWant  bool\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tError: nil,\n\t\t\tCode:  200,\n\t\t\tWant:  false,\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tError: \"\",\n\t\t\tCode:  200,\n\t\t\tWant:  false,\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tError: http.StatusConflict,\n\t\t\tCode:  409,\n\t\t\tWant:  true,\n\t\t},\n\t\t// #3\n\t\t{\n\t\t\tError: http.StatusConflict,\n\t\t\tCode:  http.StatusInternalServerError,\n\t\t\tWant:  false,\n\t\t},\n\t\t// #4\n\t\t{\n\t\t\tError: &Error{Status: http.StatusConflict},\n\t\t\tCode:  409,\n\t\t\tWant:  true,\n\t\t},\n\t\t// #5\n\t\t{\n\t\t\tError: Error{Status: http.StatusConflict},\n\t\t\tCode:  409,\n\t\t\tWant:  true,\n\t\t},\n\t\t// #6\n\t\t{\n\t\t\tError: &http.Response{StatusCode: http.StatusConflict},\n\t\t\tCode:  409,\n\t\t\tWant:  true,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tif have, want := IsStatusCode(tt.Error, tt.Code), tt.Want; have != want {\n\t\t\tt.Errorf(\"#%d: have %v, want %v\", i, have, want)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "example_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic_test\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"reflect\"\n\t\"time\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\ntype Tweet struct {\n\tUser     string                `json:\"user\"`\n\tMessage  string                `json:\"message\"`\n\tRetweets int                   `json:\"retweets\"`\n\tImage    string                `json:\"image,omitempty\"`\n\tCreated  time.Time             `json:\"created,omitempty\"`\n\tTags     []string              `json:\"tags,omitempty\"`\n\tLocation string                `json:\"location,omitempty\"`\n\tSuggest  *elastic.SuggestField `json:\"suggest_field,omitempty\"`\n}\n\nfunc Example() {\n\terrorlog := log.New(os.Stdout, \"APP \", log.LstdFlags)\n\n\t// Obtain a client. You can also provide your own HTTP client here.\n\tclient, err := elastic.NewClient(elastic.SetErrorLog(errorlog))\n\t// Trace request and response details like this\n\t// client, err := elastic.NewClient(elastic.SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\n\t// Ping the Elasticsearch server to get e.g. the version number\n\tinfo, code, err := client.Ping(\"http://127.0.0.1:9200\").Do(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Elasticsearch returned with code %d and version %s\\n\", code, info.Version.Number)\n\n\t// Getting the ES version number is quite common, so there's a shortcut\n\tesversion, err := client.ElasticsearchVersion(\"http://127.0.0.1:9200\")\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Elasticsearch version %s\\n\", esversion)\n\n\t// Use the IndexExists service to check if a specified index exists.\n\texists, err := client.IndexExists(\"twitter\").Do(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tif !exists {\n\t\t// Create a new index.\n\t\tmapping := `\n{\n\t\"settings\":{\n\t\t\"number_of_shards\":1,\n\t\t\"number_of_replicas\":0\n\t},\n\t\"mappings\":{\n\t\t\"doc\":{\n\t\t\t\"properties\":{\n\t\t\t\t\"user\":{\n\t\t\t\t\t\"type\":\"keyword\"\n\t\t\t\t},\n\t\t\t\t\"message\":{\n\t\t\t\t\t\"type\":\"text\",\n\t\t\t\t\t\"store\": true,\n\t\t\t\t\t\"fielddata\": true\n\t\t\t\t},\n                \"retweets\":{\n                    \"type\":\"long\"\n                },\n\t\t\t\t\"tags\":{\n\t\t\t\t\t\"type\":\"keyword\"\n\t\t\t\t},\n\t\t\t\t\"location\":{\n\t\t\t\t\t\"type\":\"geo_point\"\n\t\t\t\t},\n\t\t\t\t\"suggest_field\":{\n\t\t\t\t\t\"type\":\"completion\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n`\n\t\tcreateIndex, err := client.CreateIndex(\"twitter\").Body(mapping).Do(context.Background())\n\t\tif err != nil {\n\t\t\t// Handle error\n\t\t\tpanic(err)\n\t\t}\n\t\tif !createIndex.Acknowledged {\n\t\t\t// Not acknowledged\n\t\t}\n\t}\n\n\t// Index a tweet (using JSON serialization)\n\ttweet1 := Tweet{User: \"olivere\", Message: \"Take Five\", Retweets: 0}\n\tput1, err := client.Index().\n\t\tIndex(\"twitter\").\n\t\tId(\"1\").\n\t\tBodyJson(tweet1).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Indexed tweet %s to index %s, type %s\\n\", put1.Id, put1.Index, put1.Type)\n\n\t// Index a second tweet (by string)\n\ttweet2 := `{\"user\" : \"olivere\", \"message\" : \"It's a Raggy Waltz\"}`\n\tput2, err := client.Index().\n\t\tIndex(\"twitter\").\n\t\tId(\"2\").\n\t\tBodyString(tweet2).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Indexed tweet %s to index %s, type %s\\n\", put2.Id, put2.Index, put2.Type)\n\n\t// Get tweet with specified ID\n\tget1, err := client.Get().\n\t\tIndex(\"twitter\").\n\t\tId(\"1\").\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tswitch {\n\t\tcase elastic.IsNotFound(err):\n\t\t\tpanic(fmt.Sprintf(\"Document not found: %v\", err))\n\t\tcase elastic.IsTimeout(err):\n\t\t\tpanic(fmt.Sprintf(\"Timeout retrieving document: %v\", err))\n\t\tcase elastic.IsConnErr(err):\n\t\t\tpanic(fmt.Sprintf(\"Connection problem: %v\", err))\n\t\tdefault:\n\t\t\t// Some other kind of error\n\t\t\tpanic(err)\n\t\t}\n\t}\n\tfmt.Printf(\"Got document %s in version %d from index %s, type %s\\n\", get1.Id, get1.Version, get1.Index, get1.Type)\n\n\t// Refresh to make sure the documents are searchable.\n\t_, err = client.Refresh().Index(\"twitter\").Do(context.Background())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Search with a term query\n\ttermQuery := elastic.NewTermQuery(\"user\", \"olivere\")\n\tsearchResult, err := client.Search().\n\t\tIndex(\"twitter\").        // search in index \"twitter\"\n\t\tQuery(termQuery).        // specify the query\n\t\tSort(\"user\", true).      // sort by \"user\" field, ascending\n\t\tFrom(0).Size(10).        // take documents 0-9\n\t\tPretty(true).            // pretty print request and response JSON\n\t\tDo(context.Background()) // execute\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\n\t// searchResult is of type SearchResult and returns hits, suggestions,\n\t// and all kinds of other information from Elasticsearch.\n\tfmt.Printf(\"Query took %d milliseconds\\n\", searchResult.TookInMillis)\n\n\t// Each is a convenience function that iterates over hits in a search result.\n\t// It makes sure you don't need to check for nil values in the response.\n\t// However, it ignores errors in serialization. If you want full control\n\t// over iterating the hits, see below.\n\tvar ttyp Tweet\n\tfor _, item := range searchResult.Each(reflect.TypeOf(ttyp)) {\n\t\tt := item.(Tweet)\n\t\tfmt.Printf(\"Tweet by %s: %s\\n\", t.User, t.Message)\n\t}\n\t// TotalHits is another convenience function that works even when something goes wrong.\n\tfmt.Printf(\"Found a total of %d tweets\\n\", searchResult.TotalHits())\n\n\t// Here's how you iterate through results with full control over each step.\n\tif searchResult.TotalHits() > 0 {\n\t\tfmt.Printf(\"Found a total of %d tweets\\n\", searchResult.TotalHits())\n\n\t\t// Iterate through results\n\t\tfor _, hit := range searchResult.Hits.Hits {\n\t\t\t// hit.Index contains the name of the index\n\n\t\t\t// Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).\n\t\t\tvar t Tweet\n\t\t\terr := json.Unmarshal(hit.Source, &t)\n\t\t\tif err != nil {\n\t\t\t\t// Deserialization failed\n\t\t\t}\n\n\t\t\t// Work with tweet\n\t\t\tfmt.Printf(\"Tweet by %s: %s\\n\", t.User, t.Message)\n\t\t}\n\t} else {\n\t\t// No hits\n\t\tfmt.Print(\"Found no tweets\\n\")\n\t}\n\n\t// Update a tweet by the update API of Elasticsearch.\n\t// We just increment the number of retweets.\n\tscript := elastic.NewScript(\"ctx._source.retweets += params.num\").Param(\"num\", 1)\n\tupdate, err := client.Update().Index(\"twitter\").Id(\"1\").\n\t\tScript(script).\n\t\tUpsert(map[string]interface{}{\"retweets\": 0}).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"New version of tweet %q is now %d\", update.Id, update.Version)\n\n\t// ...\n\n\t// Delete an index.\n\tdeleteIndex, err := client.DeleteIndex(\"twitter\").Do(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tif !deleteIndex.Acknowledged {\n\t\t// Not acknowledged\n\t}\n}\n\nfunc ExampleNewClient_default() {\n\t// Obtain a client to the Elasticsearch instance on http://127.0.0.1:9200.\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\t// Handle error\n\t\tfmt.Printf(\"connection failed: %v\\n\", err)\n\t} else {\n\t\tfmt.Println(\"connected\")\n\t}\n\t_ = client\n\t// Output:\n\t// connected\n}\n\nfunc ExampleNewClient_cluster() {\n\t// Obtain a client for an Elasticsearch cluster of two nodes,\n\t// running on 10.0.1.1 and 10.0.1.2.\n\tclient, err := elastic.NewClient(elastic.SetURL(\"http://10.0.1.1:9200\", \"http://10.0.1.2:9200\"))\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\t_ = client\n}\n\nfunc ExampleNewClient_manyOptions() {\n\t// Obtain a client for an Elasticsearch cluster of two nodes,\n\t// running on 10.0.1.1 and 10.0.1.2. Do not run the sniffer.\n\t// Set the healthcheck interval to 10s. When requests fail,\n\t// retry 5 times. Print error messages to os.Stderr and informational\n\t// messages to os.Stdout.\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(\"http://10.0.1.1:9200\", \"http://10.0.1.2:9200\"),\n\t\telastic.SetSniff(false),\n\t\telastic.SetHealthcheckInterval(10*time.Second),\n\t\telastic.SetMaxRetries(5),\n\t\telastic.SetErrorLog(log.New(os.Stderr, \"ELASTIC \", log.LstdFlags)),\n\t\telastic.SetInfoLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\t_ = client\n}\n\nfunc ExampleIndicesExistsService() {\n\t// Get a client to the local Elasticsearch instance.\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\t// Use the IndexExists service to check if the index \"twitter\" exists.\n\texists, err := client.IndexExists(\"twitter\").Do(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tif exists {\n\t\t// ...\n\t}\n}\n\nfunc ExampleIndicesCreateService() {\n\t// Get a client to the local Elasticsearch instance.\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\t// Create a new index.\n\tcreateIndex, err := client.CreateIndex(\"twitter\").Do(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tif !createIndex.Acknowledged {\n\t\t// Not acknowledged\n\t}\n}\n\nfunc ExampleIndicesDeleteService() {\n\t// Get a client to the local Elasticsearch instance.\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\t// Delete an index.\n\tdeleteIndex, err := client.DeleteIndex(\"twitter\").Do(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\tif !deleteIndex.Acknowledged {\n\t\t// Not acknowledged\n\t}\n}\n\nfunc ExampleSearchService() {\n\t// Get a client to the local Elasticsearch instance.\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\n\t// Search with a term query\n\ttermQuery := elastic.NewTermQuery(\"user\", \"olivere\")\n\tsearchResult, err := client.Search().\n\t\tIndex(\"twitter\").        // search in index \"twitter\"\n\t\tQuery(termQuery).        // specify the query\n\t\tSort(\"user\", true).      // sort by \"user\" field, ascending\n\t\tFrom(0).Size(10).        // take documents 0-9\n\t\tPretty(true).            // pretty print request and response JSON\n\t\tDo(context.Background()) // execute\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\n\t// searchResult is of type SearchResult and returns hits, suggestions,\n\t// and all kinds of other information from Elasticsearch.\n\tfmt.Printf(\"Query took %d milliseconds\\n\", searchResult.TookInMillis)\n\n\t// Number of hits\n\tif searchResult.TotalHits() > 0 {\n\t\tfmt.Printf(\"Found a total of %d tweets\\n\", searchResult.TotalHits())\n\n\t\t// Iterate through results\n\t\tfor _, hit := range searchResult.Hits.Hits {\n\t\t\t// hit.Index contains the name of the index\n\n\t\t\t// Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).\n\t\t\tvar t Tweet\n\t\t\terr := json.Unmarshal(hit.Source, &t)\n\t\t\tif err != nil {\n\t\t\t\t// Deserialization failed\n\t\t\t}\n\n\t\t\t// Work with tweet\n\t\t\tfmt.Printf(\"Tweet by %s: %s\\n\", t.User, t.Message)\n\t\t}\n\t} else {\n\t\t// No hits\n\t\tfmt.Print(\"Found no tweets\\n\")\n\t}\n}\n\nfunc ExampleAggregations() {\n\t// Get a client to the local Elasticsearch instance.\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\n\t// Create an aggregation for users and a sub-aggregation for a date histogram of tweets (per year).\n\ttimeline := elastic.NewTermsAggregation().Field(\"user\").Size(10).OrderByCountDesc()\n\thistogram := elastic.NewDateHistogramAggregation().Field(\"created\").CalendarInterval(\"year\")\n\ttimeline = timeline.SubAggregation(\"history\", histogram)\n\n\t// Search with a term query\n\tsearchResult, err := client.Search().\n\t\tIndex(\"twitter\").                  // search in index \"twitter\"\n\t\tQuery(elastic.NewMatchAllQuery()). // return all results, but ...\n\t\tSearchType(\"count\").               // ... do not return hits, just the count\n\t\tAggregation(\"timeline\", timeline). // add our aggregation to the query\n\t\tPretty(true).                      // pretty print request and response JSON\n\t\tDo(context.Background())           // execute\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\n\t// Access \"timeline\" aggregate in search result.\n\tagg, found := searchResult.Aggregations.Terms(\"timeline\")\n\tif !found {\n\t\tlog.Fatalf(\"we should have a terms aggregation called %q\", \"timeline\")\n\t}\n\tfor _, userBucket := range agg.Buckets {\n\t\t// Every bucket should have the user field as key.\n\t\tuser := userBucket.Key\n\n\t\t// The sub-aggregation history should have the number of tweets per year.\n\t\thistogram, found := userBucket.DateHistogram(\"history\")\n\t\tif found {\n\t\t\tfor _, year := range histogram.Buckets {\n\t\t\t\tvar key string\n\t\t\t\tif s := year.KeyAsString; s != nil {\n\t\t\t\t\tkey = *s\n\t\t\t\t}\n\t\t\t\tfmt.Printf(\"user %q has %d tweets in %q\\n\", user, year.DocCount, key)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc ExampleSearchResult() {\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Do a search\n\tsearchResult, err := client.Search().Index(\"twitter\").Query(elastic.NewMatchAllQuery()).Do(context.Background())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// searchResult is of type SearchResult and returns hits, suggestions,\n\t// and all kinds of other information from Elasticsearch.\n\tfmt.Printf(\"Query took %d milliseconds\\n\", searchResult.TookInMillis)\n\n\t// Each is a utility function that iterates over hits in a search result.\n\t// It makes sure you don't need to check for nil values in the response.\n\t// However, it ignores errors in serialization. If you want full control\n\t// over iterating the hits, see below.\n\tvar ttyp Tweet\n\tfor _, item := range searchResult.Each(reflect.TypeOf(ttyp)) {\n\t\tt := item.(Tweet)\n\t\tfmt.Printf(\"Tweet by %s: %s\\n\", t.User, t.Message)\n\t}\n\tfmt.Printf(\"Found a total of %d tweets\\n\", searchResult.TotalHits())\n\n\t// Here's how you iterate hits with full control.\n\tif searchResult.TotalHits() > 0 {\n\t\tfmt.Printf(\"Found a total of %d tweets\\n\", searchResult.TotalHits())\n\n\t\t// Iterate through results\n\t\tfor _, hit := range searchResult.Hits.Hits {\n\t\t\t// hit.Index contains the name of the index\n\n\t\t\t// Deserialize hit.Source into a Tweet (could also be just a map[string]interface{}).\n\t\t\tvar t Tweet\n\t\t\terr := json.Unmarshal(hit.Source, &t)\n\t\t\tif err != nil {\n\t\t\t\t// Deserialization failed\n\t\t\t}\n\n\t\t\t// Work with tweet\n\t\t\tfmt.Printf(\"Tweet by %s: %s\\n\", t.User, t.Message)\n\t\t}\n\t} else {\n\t\t// No hits\n\t\tfmt.Print(\"Found no tweets\\n\")\n\t}\n}\n\nfunc ExampleClusterHealthService() {\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Get cluster health\n\tres, err := client.ClusterHealth().Index(\"twitter\").Do(context.Background())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tif res == nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Cluster status is %q\\n\", res.Status)\n}\n\nfunc ExampleClusterHealthService_WaitForStatus() {\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Wait for status green\n\tres, err := client.ClusterHealth().WaitForStatus(\"green\").Timeout(\"15s\").Do(context.Background())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tif res.TimedOut {\n\t\tfmt.Printf(\"time out waiting for cluster status %q\\n\", \"green\")\n\t} else {\n\t\tfmt.Printf(\"cluster status is %q\\n\", res.Status)\n\t}\n}\n\nfunc ExampleClusterStateService() {\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Get cluster state\n\tres, err := client.ClusterState().Metric(\"version\").Do(context.Background())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Cluster %q has version %d\", res.ClusterName, res.Version)\n}\n"
  },
  {
    "path": "exists.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// ExistsService checks for the existence of a document using HEAD.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-get.html\n// for details.\ntype ExistsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid         string\n\tindex      string\n\ttyp        string\n\tpreference string\n\trealtime   *bool\n\trefresh    string\n\trouting    string\n\tparent     string\n}\n\n// NewExistsService creates a new ExistsService.\nfunc NewExistsService(client *Client) *ExistsService {\n\treturn &ExistsService{\n\t\tclient: client,\n\t\ttyp:    \"_doc\",\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ExistsService) Pretty(pretty bool) *ExistsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ExistsService) Human(human bool) *ExistsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ExistsService) ErrorTrace(errorTrace bool) *ExistsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ExistsService) FilterPath(filterPath ...string) *ExistsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ExistsService) Header(name string, value string) *ExistsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ExistsService) Headers(headers http.Header) *ExistsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is the document ID.\nfunc (s *ExistsService) Id(id string) *ExistsService {\n\ts.id = id\n\treturn s\n}\n\n// Index is the name of the index.\nfunc (s *ExistsService) Index(index string) *ExistsService {\n\ts.index = index\n\treturn s\n}\n\n// Type is the type of the document (use `_all` to fetch the first document\n// matching the ID across all types).\nfunc (s *ExistsService) Type(typ string) *ExistsService {\n\ts.typ = typ\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be performed on (default: random).\nfunc (s *ExistsService) Preference(preference string) *ExistsService {\n\ts.preference = preference\n\treturn s\n}\n\n// Realtime specifies whether to perform the operation in realtime or search mode.\nfunc (s *ExistsService) Realtime(realtime bool) *ExistsService {\n\ts.realtime = &realtime\n\treturn s\n}\n\n// Refresh the shard containing the document before performing the operation.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *ExistsService) Refresh(refresh string) *ExistsService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// Routing is a specific routing value.\nfunc (s *ExistsService) Routing(routing string) *ExistsService {\n\ts.routing = routing\n\treturn s\n}\n\n// Parent is the ID of the parent document.\nfunc (s *ExistsService) Parent(parent string) *ExistsService {\n\ts.parent = parent\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ExistsService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/{type}/{id}\", map[string]string{\n\t\t\"id\":    s.id,\n\t\t\"index\": s.index,\n\t\t\"type\":  s.typ,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.realtime != nil {\n\t\tparams.Set(\"realtime\", fmt.Sprint(*s.realtime))\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Set(\"refresh\", s.refresh)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.parent != \"\" {\n\t\tparams.Set(\"parent\", s.parent)\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ExistsService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif s.typ == \"\" {\n\t\tinvalid = append(invalid, \"Type\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *ExistsService) Do(ctx context.Context) (bool, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn false, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:       \"HEAD\",\n\t\tPath:         path,\n\t\tParams:       params,\n\t\tIgnoreErrors: []int{404},\n\t\tHeaders:      s.headers,\n\t})\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\t// Return operation response\n\tswitch res.StatusCode {\n\tcase http.StatusOK:\n\t\treturn true, nil\n\tcase http.StatusNotFound:\n\t\treturn false, nil\n\tdefault:\n\t\treturn false, fmt.Errorf(\"elastic: got HTTP code %d when it should have been either 200 or 404\", res.StatusCode)\n\t}\n}\n"
  },
  {
    "path": "exists_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestExists(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\texists, err := client.Exists().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !exists {\n\t\tt.Fatal(\"expected document to exist\")\n\t}\n}\n\nfunc TestExistsValidate(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// No index -> fail with error\n\tres, err := NewExistsService(client).Id(\"1\").Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected Delete to fail without index name\")\n\t}\n\tif res != false {\n\t\tt.Fatalf(\"expected result to be false; got: %v\", res)\n\t}\n\n\t// No id -> fail with error\n\tres, err = NewExistsService(client).Index(testIndexName).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected Delete to fail without index name\")\n\t}\n\tif res != false {\n\t\tt.Fatalf(\"expected result to be false; got: %v\", res)\n\t}\n}\n"
  },
  {
    "path": "explain.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// ExplainService computes a score explanation for a query and\n// a specific document.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-explain.html.\ntype ExplainService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid                     string\n\tindex                  string\n\ttyp                    string\n\tq                      string\n\trouting                string\n\tlenient                *bool\n\tanalyzer               string\n\tdf                     string\n\tfields                 []string\n\tlowercaseExpandedTerms *bool\n\txSourceInclude         []string\n\tanalyzeWildcard        *bool\n\tparent                 string\n\tpreference             string\n\txSource                []string\n\tdefaultOperator        string\n\txSourceExclude         []string\n\tsource                 string\n\tbodyJson               interface{}\n\tbodyString             string\n}\n\n// NewExplainService creates a new ExplainService.\nfunc NewExplainService(client *Client) *ExplainService {\n\treturn &ExplainService{\n\t\tclient:         client,\n\t\ttyp:            \"_doc\",\n\t\txSource:        make([]string, 0),\n\t\txSourceExclude: make([]string, 0),\n\t\tfields:         make([]string, 0),\n\t\txSourceInclude: make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ExplainService) Pretty(pretty bool) *ExplainService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ExplainService) Human(human bool) *ExplainService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ExplainService) ErrorTrace(errorTrace bool) *ExplainService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ExplainService) FilterPath(filterPath ...string) *ExplainService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ExplainService) Header(name string, value string) *ExplainService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ExplainService) Headers(headers http.Header) *ExplainService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is the document ID.\nfunc (s *ExplainService) Id(id string) *ExplainService {\n\ts.id = id\n\treturn s\n}\n\n// Index is the name of the index.\nfunc (s *ExplainService) Index(index string) *ExplainService {\n\ts.index = index\n\treturn s\n}\n\n// Type is the type of the document.\n//\n// Deprecated: Types are in the process of being removed.\nfunc (s *ExplainService) Type(typ string) *ExplainService {\n\ts.typ = typ\n\treturn s\n}\n\n// Source is the URL-encoded query definition (instead of using the request body).\nfunc (s *ExplainService) Source(source string) *ExplainService {\n\ts.source = source\n\treturn s\n}\n\n// XSourceExclude is a list of fields to exclude from the returned _source field.\nfunc (s *ExplainService) XSourceExclude(xSourceExclude ...string) *ExplainService {\n\ts.xSourceExclude = append(s.xSourceExclude, xSourceExclude...)\n\treturn s\n}\n\n// Lenient specifies whether format-based query failures\n// (such as providing text to a numeric field) should be ignored.\nfunc (s *ExplainService) Lenient(lenient bool) *ExplainService {\n\ts.lenient = &lenient\n\treturn s\n}\n\n// Query in the Lucene query string syntax.\nfunc (s *ExplainService) Q(q string) *ExplainService {\n\ts.q = q\n\treturn s\n}\n\n// Routing sets a specific routing value.\nfunc (s *ExplainService) Routing(routing string) *ExplainService {\n\ts.routing = routing\n\treturn s\n}\n\n// AnalyzeWildcard specifies whether wildcards and prefix queries\n// in the query string query should be analyzed (default: false).\nfunc (s *ExplainService) AnalyzeWildcard(analyzeWildcard bool) *ExplainService {\n\ts.analyzeWildcard = &analyzeWildcard\n\treturn s\n}\n\n// Analyzer is the analyzer for the query string query.\nfunc (s *ExplainService) Analyzer(analyzer string) *ExplainService {\n\ts.analyzer = analyzer\n\treturn s\n}\n\n// Df is the default field for query string query (default: _all).\nfunc (s *ExplainService) Df(df string) *ExplainService {\n\ts.df = df\n\treturn s\n}\n\n// Fields is a list of fields to return in the response.\nfunc (s *ExplainService) Fields(fields ...string) *ExplainService {\n\ts.fields = append(s.fields, fields...)\n\treturn s\n}\n\n// LowercaseExpandedTerms specifies whether query terms should be lowercased.\nfunc (s *ExplainService) LowercaseExpandedTerms(lowercaseExpandedTerms bool) *ExplainService {\n\ts.lowercaseExpandedTerms = &lowercaseExpandedTerms\n\treturn s\n}\n\n// XSourceInclude is a list of fields to extract and return from the _source field.\nfunc (s *ExplainService) XSourceInclude(xSourceInclude ...string) *ExplainService {\n\ts.xSourceInclude = append(s.xSourceInclude, xSourceInclude...)\n\treturn s\n}\n\n// DefaultOperator is the default operator for query string query (AND or OR).\nfunc (s *ExplainService) DefaultOperator(defaultOperator string) *ExplainService {\n\ts.defaultOperator = defaultOperator\n\treturn s\n}\n\n// Parent is the ID of the parent document.\nfunc (s *ExplainService) Parent(parent string) *ExplainService {\n\ts.parent = parent\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be performed on (default: random).\nfunc (s *ExplainService) Preference(preference string) *ExplainService {\n\ts.preference = preference\n\treturn s\n}\n\n// XSource is true or false to return the _source field or not, or a list of fields to return.\nfunc (s *ExplainService) XSource(xSource ...string) *ExplainService {\n\ts.xSource = append(s.xSource, xSource...)\n\treturn s\n}\n\n// Query sets a query definition using the Query DSL.\nfunc (s *ExplainService) Query(query Query) *ExplainService {\n\tsrc, err := query.Source()\n\tif err != nil {\n\t\t// Do nothing in case of an error\n\t\treturn s\n\t}\n\tbody := make(map[string]interface{})\n\tbody[\"query\"] = src\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyJson sets the query definition using the Query DSL.\nfunc (s *ExplainService) BodyJson(body interface{}) *ExplainService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString sets the query definition using the Query DSL as a string.\nfunc (s *ExplainService) BodyString(body string) *ExplainService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ExplainService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar path string\n\tvar err error\n\n\tif s.typ == \"\" || s.typ == \"_doc\" {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_explain/{id}\", map[string]string{\n\t\t\t\"id\":    s.id,\n\t\t\t\"index\": s.index,\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/{id}/_explain\", map[string]string{\n\t\t\t\"id\":    s.id,\n\t\t\t\"index\": s.index,\n\t\t\t\"type\":  s.typ,\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif len(s.xSource) > 0 {\n\t\tparams.Set(\"_source\", strings.Join(s.xSource, \",\"))\n\t}\n\tif s.defaultOperator != \"\" {\n\t\tparams.Set(\"default_operator\", s.defaultOperator)\n\t}\n\tif s.parent != \"\" {\n\t\tparams.Set(\"parent\", s.parent)\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif s.source != \"\" {\n\t\tparams.Set(\"source\", s.source)\n\t}\n\tif len(s.xSourceExclude) > 0 {\n\t\tparams.Set(\"_source_excludes\", strings.Join(s.xSourceExclude, \",\"))\n\t}\n\tif s.lenient != nil {\n\t\tparams.Set(\"lenient\", fmt.Sprintf(\"%v\", *s.lenient))\n\t}\n\tif s.q != \"\" {\n\t\tparams.Set(\"q\", s.q)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif len(s.fields) > 0 {\n\t\tparams.Set(\"fields\", strings.Join(s.fields, \",\"))\n\t}\n\tif s.lowercaseExpandedTerms != nil {\n\t\tparams.Set(\"lowercase_expanded_terms\", fmt.Sprintf(\"%v\", *s.lowercaseExpandedTerms))\n\t}\n\tif len(s.xSourceInclude) > 0 {\n\t\tparams.Set(\"_source_includes\", strings.Join(s.xSourceInclude, \",\"))\n\t}\n\tif s.analyzeWildcard != nil {\n\t\tparams.Set(\"analyze_wildcard\", fmt.Sprintf(\"%v\", *s.analyzeWildcard))\n\t}\n\tif s.analyzer != \"\" {\n\t\tparams.Set(\"analyzer\", s.analyzer)\n\t}\n\tif s.df != \"\" {\n\t\tparams.Set(\"df\", s.df)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ExplainService) Validate() error {\n\tvar invalid []string\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif s.typ == \"\" {\n\t\tinvalid = append(invalid, \"Type\")\n\t}\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *ExplainService) Do(ctx context.Context) (*ExplainResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(ExplainResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// ExplainResponse is the response of ExplainService.Do.\ntype ExplainResponse struct {\n\tIndex       string                 `json:\"_index\"`\n\tType        string                 `json:\"_type\"`\n\tId          string                 `json:\"_id\"`\n\tMatched     bool                   `json:\"matched\"`\n\tExplanation map[string]interface{} `json:\"explanation\"`\n}\n"
  },
  {
    "path": "explain_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestExplain(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\n\t// Add a document\n\tindexResult, err := client.Index().\n\t\tIndex(testIndexName).\n\t\tId(\"1\").\n\t\tBodyJson(&tweet1).\n\t\tRefresh(\"true\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indexResult == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", indexResult)\n\t}\n\n\t// Explain\n\tquery := NewTermQuery(\"user\", \"olivere\")\n\texpl, err := client.Explain(testIndexName, \"_doc\", \"1\").Query(query).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif expl == nil {\n\t\tt.Fatal(\"expected to return an explanation\")\n\t}\n\tif !expl.Matched {\n\t\tt.Errorf(\"expected matched to be %v; got: %v\", true, expl.Matched)\n\t}\n}\n"
  },
  {
    "path": "fetch_source_context.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"net/url\"\n\t\"strings\"\n)\n\n// FetchSourceContext enables source filtering, i.e. it allows control\n// over how the _source field is returned with every hit. It is used\n// with various endpoints, e.g. when searching for documents, retrieving\n// individual documents, or even updating documents.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-source-filtering.html\n// for details.\ntype FetchSourceContext struct {\n\tfetchSource bool\n\tincludes    []string\n\texcludes    []string\n}\n\n// NewFetchSourceContext returns a new FetchSourceContext.\nfunc NewFetchSourceContext(fetchSource bool) *FetchSourceContext {\n\treturn &FetchSourceContext{\n\t\tfetchSource: fetchSource,\n\t\tincludes:    make([]string, 0),\n\t\texcludes:    make([]string, 0),\n\t}\n}\n\n// FetchSource indicates whether to return the _source.\nfunc (fsc *FetchSourceContext) FetchSource() bool {\n\treturn fsc.fetchSource\n}\n\n// SetFetchSource specifies whether to return the _source.\nfunc (fsc *FetchSourceContext) SetFetchSource(fetchSource bool) {\n\tfsc.fetchSource = fetchSource\n}\n\n// Include indicates to return specific parts of the _source.\n// Wildcards are allowed here.\nfunc (fsc *FetchSourceContext) Include(includes ...string) *FetchSourceContext {\n\tfsc.includes = append(fsc.includes, includes...)\n\treturn fsc\n}\n\n// Exclude indicates to exclude specific parts of the _source.\n// Wildcards are allowed here.\nfunc (fsc *FetchSourceContext) Exclude(excludes ...string) *FetchSourceContext {\n\tfsc.excludes = append(fsc.excludes, excludes...)\n\treturn fsc\n}\n\n// Source returns the JSON-serializable data to be used in a body.\nfunc (fsc *FetchSourceContext) Source() (interface{}, error) {\n\tif !fsc.fetchSource {\n\t\treturn false, nil\n\t}\n\tif len(fsc.includes) == 0 && len(fsc.excludes) == 0 {\n\t\treturn true, nil\n\t}\n\tsrc := make(map[string]interface{})\n\tif len(fsc.includes) > 0 {\n\t\tsrc[\"includes\"] = fsc.includes\n\t}\n\tif len(fsc.excludes) > 0 {\n\t\tsrc[\"excludes\"] = fsc.excludes\n\t}\n\treturn src, nil\n}\n\n// Query returns the parameters in a form suitable for a URL query string.\nfunc (fsc *FetchSourceContext) Query() url.Values {\n\tparams := url.Values{}\n\tif fsc.fetchSource {\n\t\tif len(fsc.includes) > 0 {\n\t\t\tparams.Add(\"_source_includes\", strings.Join(fsc.includes, \",\"))\n\t\t}\n\t\tif len(fsc.excludes) > 0 {\n\t\t\tparams.Add(\"_source_excludes\", strings.Join(fsc.excludes, \",\"))\n\t\t}\n\t} else {\n\t\tparams.Add(\"_source\", \"false\")\n\t}\n\treturn params\n}\n"
  },
  {
    "path": "fetch_source_context_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestFetchSourceContextNoFetchSource(t *testing.T) {\n\tbuilder := NewFetchSourceContext(false)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `false`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFetchSourceContextNoFetchSourceIgnoreIncludesAndExcludes(t *testing.T) {\n\tbuilder := NewFetchSourceContext(false).Include(\"a\", \"b\").Exclude(\"c\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `false`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFetchSourceContextFetchSource(t *testing.T) {\n\tbuilder := NewFetchSourceContext(true)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `true`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFetchSourceContextFetchSourceWithIncludesOnly(t *testing.T) {\n\tbuilder := NewFetchSourceContext(true).Include(\"a\", \"b\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"includes\":[\"a\",\"b\"]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFetchSourceContextFetchSourceWithIncludesAndExcludes(t *testing.T) {\n\tbuilder := NewFetchSourceContext(true).Include(\"a\", \"b\").Exclude(\"c\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"excludes\":[\"c\"],\"includes\":[\"a\",\"b\"]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFetchSourceContextQueryDefaults(t *testing.T) {\n\tbuilder := NewFetchSourceContext(true)\n\tvalues := builder.Query()\n\tgot := values.Encode()\n\texpected := \"\"\n\tif got != expected {\n\t\tt.Errorf(\"expected %q; got: %q\", expected, got)\n\t}\n}\n\nfunc TestFetchSourceContextQueryNoFetchSource(t *testing.T) {\n\tbuilder := NewFetchSourceContext(false)\n\tvalues := builder.Query()\n\tgot := values.Encode()\n\texpected := \"_source=false\"\n\tif got != expected {\n\t\tt.Errorf(\"expected %q; got: %q\", expected, got)\n\t}\n}\n\nfunc TestFetchSourceContextQueryFetchSourceWithIncludesAndExcludes(t *testing.T) {\n\tbuilder := NewFetchSourceContext(true).Include(\"a\", \"b\").Exclude(\"c\")\n\tvalues := builder.Query()\n\tgot := values.Encode()\n\texpected := \"_source_excludes=c&_source_includes=a%2Cb\"\n\tif got != expected {\n\t\tt.Errorf(\"expected %q; got: %q\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "field_caps.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// FieldCapsService allows retrieving the capabilities of fields among multiple indices.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-field-caps.html\n// for details\ntype FieldCapsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tallowNoIndices    *bool\n\texpandWildcards   string\n\tfields            []string\n\tignoreUnavailable *bool\n\tincludeUnmapped   *bool\n\tbodyJson          interface{}\n\tbodyString        string\n}\n\n// NewFieldCapsService creates a new FieldCapsService\nfunc NewFieldCapsService(client *Client) *FieldCapsService {\n\treturn &FieldCapsService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *FieldCapsService) Pretty(pretty bool) *FieldCapsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *FieldCapsService) Human(human bool) *FieldCapsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *FieldCapsService) ErrorTrace(errorTrace bool) *FieldCapsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *FieldCapsService) FilterPath(filterPath ...string) *FieldCapsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *FieldCapsService) Header(name string, value string) *FieldCapsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *FieldCapsService) Headers(headers http.Header) *FieldCapsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names; use `_all` or empty string to perform\n// the operation on all indices.\nfunc (s *FieldCapsService) Index(index ...string) *FieldCapsService {\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices expression\n// resolves into no concrete indices.\n// (This includes `_all` string or when no indices have been specified).\nfunc (s *FieldCapsService) AllowNoIndices(allowNoIndices bool) *FieldCapsService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *FieldCapsService) ExpandWildcards(expandWildcards string) *FieldCapsService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// Fields is a list of fields for to get field capabilities.\nfunc (s *FieldCapsService) Fields(fields ...string) *FieldCapsService {\n\ts.fields = append(s.fields, fields...)\n\treturn s\n}\n\n// IgnoreUnavailable is documented as: Whether specified concrete indices should be ignored when unavailable (missing or closed).\nfunc (s *FieldCapsService) IgnoreUnavailable(ignoreUnavailable bool) *FieldCapsService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// IncludeUnmapped specifies whether unmapped fields whould be included in the response.\nfunc (s *FieldCapsService) IncludeUnmapped(includeUnmapped bool) *FieldCapsService {\n\ts.includeUnmapped = &includeUnmapped\n\treturn s\n}\n\n// BodyJson is documented as: Field json objects containing the name and optionally a range to filter out indices result, that have results outside the defined bounds.\nfunc (s *FieldCapsService) BodyJson(body interface{}) *FieldCapsService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is documented as: Field json objects containing the name and optionally a range to filter out indices result, that have results outside the defined bounds.\nfunc (s *FieldCapsService) BodyString(body string) *FieldCapsService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *FieldCapsService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_field_caps\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_field_caps\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprint(*s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif len(s.fields) > 0 {\n\t\tparams.Set(\"fields\", strings.Join(s.fields, \",\"))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*s.ignoreUnavailable))\n\t}\n\tif s.includeUnmapped != nil {\n\t\tparams.Set(\"include_unmapped\", fmt.Sprint(*s.includeUnmapped))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *FieldCapsService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *FieldCapsService) Do(ctx context.Context) (*FieldCapsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:       \"POST\",\n\t\tPath:         path,\n\t\tParams:       params,\n\t\tBody:         body,\n\t\tIgnoreErrors: []int{http.StatusNotFound},\n\t\tHeaders:      s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// TODO(oe): Is 404 really a valid response here?\n\tif res.StatusCode == http.StatusNotFound {\n\t\treturn &FieldCapsResponse{}, nil\n\t}\n\n\t// Return operation response\n\tret := new(FieldCapsResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Request --\n\n// FieldCapsRequest can be used to set up the body to be used in the\n// Field Capabilities API.\ntype FieldCapsRequest struct {\n\tFields          []string        `json:\"fields\"` // list of fields to retrieve\n\tIndexFilter     Query           `json:\"index_filter,omitempty\"`\n\tRuntimeMappings RuntimeMappings `json:\"runtime_mappings,omitempty\"`\n}\n\n// -- Response --\n\n// FieldCapsResponse contains field capabilities.\ntype FieldCapsResponse struct {\n\tIndices []string                 `json:\"indices,omitempty\"` // list of index names\n\tFields  map[string]FieldCapsType `json:\"fields,omitempty\"`  // Name -> type -> caps\n}\n\n// FieldCapsType represents a mapping from type (e.g. keyword)\n// to capabilities.\ntype FieldCapsType map[string]FieldCaps // type -> caps\n\n// FieldCaps contains capabilities of an individual field.\ntype FieldCaps struct {\n\tType                   string                 `json:\"type\"`\n\tMetadataField          bool                   `json:\"metadata_field\"`\n\tSearchable             bool                   `json:\"searchable\"`\n\tAggregatable           bool                   `json:\"aggregatable\"`\n\tIndices                []string               `json:\"indices,omitempty\"`\n\tNonSearchableIndices   []string               `json:\"non_searchable_indices,omitempty\"`\n\tNonAggregatableIndices []string               `json:\"non_aggregatable_indices,omitempty\"`\n\tMeta                   map[string]interface{} `json:\"meta,omitempty\"`\n}\n"
  },
  {
    "path": "field_caps_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n)\n\nfunc TestFieldCapsURLs(t *testing.T) {\n\ttests := []struct {\n\t\tService        *FieldCapsService\n\t\tExpectedPath   string\n\t\tExpectedParams url.Values\n\t}{\n\t\t{\n\t\t\tService:        &FieldCapsService{},\n\t\t\tExpectedPath:   \"/_field_caps\",\n\t\t\tExpectedParams: url.Values{},\n\t\t},\n\t\t{\n\t\t\tService: &FieldCapsService{\n\t\t\t\tindex: []string{\"index1\", \"index2\"},\n\t\t\t},\n\t\t\tExpectedPath:   \"/index1%2Cindex2/_field_caps\",\n\t\t\tExpectedParams: url.Values{},\n\t\t},\n\t\t{\n\t\t\tService: &FieldCapsService{\n\t\t\t\tindex:  []string{\"index_*\"},\n\t\t\t\tpretty: boolPtr(true),\n\t\t\t},\n\t\t\tExpectedPath:   \"/index_%2A/_field_caps\",\n\t\t\tExpectedParams: url.Values{\"pretty\": []string{\"true\"}},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tgotPath, gotParams, err := test.Service.buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t\t}\n\t\tif gotPath != test.ExpectedPath {\n\t\t\tt.Errorf(\"expected URL path = %q; got: %q\", test.ExpectedPath, gotPath)\n\t\t}\n\t\tif gotParams.Encode() != test.ExpectedParams.Encode() {\n\t\t\tt.Errorf(\"expected URL params = %v; got: %v\", test.ExpectedParams, gotParams)\n\t\t}\n\t}\n}\n\nfunc TestFieldCapsRequestSerialize(t *testing.T) {\n\treq := &FieldCapsRequest{\n\t\tFields: []string{\"creation_date\", \"answer_count\"},\n\t}\n\tdata, err := json.Marshal(req)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"fields\":[\"creation_date\",\"answer_count\"]}`\n\tif got != expected {\n\t\tt.Fatalf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFieldCapsRequestDeserialize(t *testing.T) {\n\tbody := `{\n\t\t\"fields\" : [\"creation_date\", \"answer_count\"]\n\t}`\n\n\tvar request FieldCapsRequest\n\tif err := json.Unmarshal([]byte(body), &request); err != nil {\n\t\tt.Fatalf(\"unexpected error during unmarshalling: %v\", err)\n\t}\n\n\tsort.Sort(lexicographically{request.Fields})\n\n\texpectedFields := []string{\"answer_count\", \"creation_date\"}\n\tif !reflect.DeepEqual(request.Fields, expectedFields) {\n\t\tt.Fatalf(\"expected fields to be %v, got %v\", expectedFields, request.Fields)\n\t}\n}\n\nfunc TestFieldCapsResponse(t *testing.T) {\n\tbody := `{\n\t\t\"_shards\": {\n\t\t\t\t\"total\": 1,\n\t\t\t\t\"successful\": 1,\n\t\t\t\t\"failed\": 0\n\t\t},\n\t\t\"fields\": {\n\t\t\t\"rating\": {\n\t\t\t\t\"long\": {\n\t\t\t\t\t\"searchable\": true,\n\t\t\t\t\t\"aggregatable\": false,\n\t\t\t\t\t\"indices\": [\"index1\", \"index2\"],\n\t\t\t\t\t\"non_aggregatable_indices\": [\"index1\"]\n\t\t\t\t},\n\t\t\t\t\"keyword\": {\n\t\t\t\t\t\"searchable\": false,\n\t\t\t\t\t\"aggregatable\": true,\n\t\t\t\t\t\"indices\": [\"index3\", \"index4\"],\n\t\t\t\t\t\"non_searchable_indices\": [\"index4\"]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"title\": {\n\t\t\t\t\"text\": {\n\t\t\t\t\t\"searchable\": true,\n\t\t\t\t\t\"aggregatable\": false\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}`\n\n\tvar resp FieldCapsResponse\n\tif err := json.Unmarshal([]byte(body), &resp); err != nil {\n\t\tt.Errorf(\"unexpected error during unmarshalling: %v\", err)\n\t}\n\n\tfield, ok := resp.Fields[\"rating\"]\n\tif !ok {\n\t\tt.Errorf(\"expected rating to be in the fields map, didn't find it\")\n\t}\n\t{\n\t\tcaps, ok := field[\"long\"]\n\t\tif !ok {\n\t\t\tt.Errorf(\"expected rating.long caps to be found\")\n\t\t}\n\t\tif want, have := true, caps.Searchable; want != have {\n\t\t\tt.Errorf(\"expected rating.long.searchable to be %v, got %v\", want, have)\n\t\t}\n\t\tif want, have := false, caps.Aggregatable; want != have {\n\t\t\tt.Errorf(\"expected rating.long.aggregatable to be %v, got %v\", want, have)\n\t\t}\n\t\tif want, have := []string{\"index1\", \"index2\"}, caps.Indices; !reflect.DeepEqual(want, have) {\n\t\t\tt.Errorf(\"expected rating.long.indices to be %v, got %v\", want, have)\n\t\t}\n\t\tif want, have := []string{\"index1\"}, caps.NonAggregatableIndices; !reflect.DeepEqual(want, have) {\n\t\t\tt.Errorf(\"expected rating.long.non_aggregatable_indices to be %v, got %v\", want, have)\n\t\t}\n\t\tif want, have := 0, len(caps.NonSearchableIndices); want != have {\n\t\t\tt.Errorf(\"expected rating.keyword.non_searchable_indices to be %v, got %v\", want, have)\n\t\t}\n\t}\n\t{\n\t\tcaps, ok := field[\"keyword\"]\n\t\tif !ok {\n\t\t\tt.Errorf(\"expected rating.keyword caps to be found\")\n\t\t}\n\t\tif want, have := false, caps.Searchable; want != have {\n\t\t\tt.Errorf(\"expected rating.keyword.searchable to be %v, got %v\", want, have)\n\t\t}\n\t\tif want, have := true, caps.Aggregatable; want != have {\n\t\t\tt.Errorf(\"expected rating.keyword.aggregatable to be %v, got %v\", want, have)\n\t\t}\n\t\tif want, have := []string{\"index3\", \"index4\"}, caps.Indices; !reflect.DeepEqual(want, have) {\n\t\t\tt.Errorf(\"expected rating.keyword.indices to be %v, got %v\", want, have)\n\t\t}\n\t\tif want, have := 0, len(caps.NonAggregatableIndices); want != have {\n\t\t\tt.Errorf(\"expected rating.keyword.non_aggregatable_indices to be %v, got %v\", want, have)\n\t\t}\n\t\tif want, have := []string{\"index4\"}, caps.NonSearchableIndices; !reflect.DeepEqual(want, have) {\n\t\t\tt.Errorf(\"expected rating.keyword.non_searchable_indices to be %v, got %v\", want, have)\n\t\t}\n\t}\n}\n\nfunc TestFieldCapsIntegrationTest(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tres, err := client.FieldCaps(\"_all\").Fields(\"user\", \"message\", \"retweets\", \"created\").Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected response; got: %v\", res)\n\t}\n}\n"
  },
  {
    "path": "geo_point.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n)\n\n// GeoPoint is a geographic position described via latitude and longitude.\ntype GeoPoint struct {\n\tLat float64 `json:\"lat\"`\n\tLon float64 `json:\"lon\"`\n}\n\n// Source returns the object to be serialized in Elasticsearch DSL.\nfunc (pt *GeoPoint) Source() map[string]float64 {\n\treturn map[string]float64{\n\t\t\"lat\": pt.Lat,\n\t\t\"lon\": pt.Lon,\n\t}\n}\n\n// MarshalJSON encodes the GeoPoint to JSON.\nfunc (pt *GeoPoint) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(pt.Source())\n}\n\n// GeoPointFromLatLon initializes a new GeoPoint by latitude and longitude.\nfunc GeoPointFromLatLon(lat, lon float64) *GeoPoint {\n\treturn &GeoPoint{Lat: lat, Lon: lon}\n}\n\n// GeoPointFromString initializes a new GeoPoint by a string that is\n// formatted as \"{latitude},{longitude}\", e.g. \"40.10210,-70.12091\".\nfunc GeoPointFromString(latLon string) (*GeoPoint, error) {\n\tlatlon := strings.SplitN(latLon, \",\", 2)\n\tif len(latlon) != 2 {\n\t\treturn nil, fmt.Errorf(\"elastic: %s is not a valid geo point string\", latLon)\n\t}\n\tlat, err := strconv.ParseFloat(latlon[0], 64)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlon, err := strconv.ParseFloat(latlon[1], 64)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn &GeoPoint{Lat: lat, Lon: lon}, nil\n}\n"
  },
  {
    "path": "geo_point_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGeoPointSource(t *testing.T) {\n\tpt := GeoPoint{Lat: 40, Lon: -70}\n\n\tdata, err := json.Marshal(pt.Source())\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"lat\":40,\"lon\":-70}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoPointMarshalJSON(t *testing.T) {\n\tpt := GeoPoint{Lat: 40, Lon: -70}\n\n\tdata, err := json.Marshal(pt)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"lat\":40,\"lon\":-70}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoPointIndexAndSearch(t *testing.T) {\n\tclient := setupTestClient(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Create index\n\tmapping := `\n\t{\n\t\t\"settings\":{\n\t\t\t\"number_of_shards\":1,\n\t\t\t\"number_of_replicas\":0\n\t\t},\n\t\t\"mappings\":{\n\t\t\t\"properties\":{\n\t\t\t\t\"name\":{\n\t\t\t\t\t\"type\":\"keyword\"\n\t\t\t\t},\n\t\t\t\t\"location\":{\n\t\t\t\t\t\"type\":\"geo_point\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`\n\tcreateIndex, err := client.CreateIndex(testIndexName).Body(mapping).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndex)\n\t}\n\n\t// Add document\n\ttype City struct {\n\t\tName     string    `json:\"name\"`\n\t\tLocation *GeoPoint `json:\"location\"`\n\t}\n\tmunich := &City{\n\t\tName:     \"München\",\n\t\tLocation: GeoPointFromLatLon(48.137154, 11.576124),\n\t}\n\t_, err = client.Index().Index(testIndexName).Id(\"1\").BodyJson(&munich).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Refresh\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Get document\n\tq := NewGeoDistanceQuery(\"location\")\n\tq = q.GeoPoint(GeoPointFromLatLon(48, 11))\n\tq = q.Distance(\"50km\")\n\tres, err := client.\n\t\tSearch(testIndexName).\n\t\tQuery(q).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := int64(1), res.TotalHits(); want != have {\n\t\tt.Fatalf(\"TotalHits: want %d, have %d\", want, have)\n\t}\n\tvar doc City\n\tif err := json.Unmarshal(res.Hits.Hits[0].Source, &doc); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := munich.Name, doc.Name; want != have {\n\t\tt.Fatalf(\"Name: want %q, have %q\", want, have)\n\t}\n\tif want, have := munich.Location.Lat, doc.Location.Lat; want != have {\n\t\tt.Fatalf(\"Lat: want %v, have %v\", want, have)\n\t}\n\tif want, have := munich.Location.Lon, doc.Location.Lon; want != have {\n\t\tt.Fatalf(\"Lon: want %v, have %v\", want, have)\n\t}\n}\n"
  },
  {
    "path": "get.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// GetService allows to get a typed JSON document from the index based\n// on its id.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-get.html\n// for details.\ntype GetService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex                         string\n\ttyp                           string\n\tid                            string\n\trouting                       string\n\tpreference                    string\n\tstoredFields                  []string\n\trefresh                       string\n\trealtime                      *bool\n\tfsc                           *FetchSourceContext\n\tversion                       interface{}\n\tversionType                   string\n\tparent                        string\n\tignoreErrorsOnGeneratedFields *bool\n}\n\n// NewGetService creates a new GetService.\nfunc NewGetService(client *Client) *GetService {\n\treturn &GetService{\n\t\tclient: client,\n\t\ttyp:    \"_doc\",\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *GetService) Pretty(pretty bool) *GetService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *GetService) Human(human bool) *GetService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *GetService) ErrorTrace(errorTrace bool) *GetService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *GetService) FilterPath(filterPath ...string) *GetService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *GetService) Header(name string, value string) *GetService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *GetService) Headers(headers http.Header) *GetService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the index.\nfunc (s *GetService) Index(index string) *GetService {\n\ts.index = index\n\treturn s\n}\n\n// Type is the type of the document\n//\n// Deprecated: Types are in the process of being removed.\nfunc (s *GetService) Type(typ string) *GetService {\n\ts.typ = typ\n\treturn s\n}\n\n// Id is the document ID.\nfunc (s *GetService) Id(id string) *GetService {\n\ts.id = id\n\treturn s\n}\n\n// Parent is the ID of the parent document.\nfunc (s *GetService) Parent(parent string) *GetService {\n\ts.parent = parent\n\treturn s\n}\n\n// Routing is the specific routing value.\nfunc (s *GetService) Routing(routing string) *GetService {\n\ts.routing = routing\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be performed on (default: random).\nfunc (s *GetService) Preference(preference string) *GetService {\n\ts.preference = preference\n\treturn s\n}\n\n// StoredFields is a list of fields to return in the response.\nfunc (s *GetService) StoredFields(storedFields ...string) *GetService {\n\ts.storedFields = append(s.storedFields, storedFields...)\n\treturn s\n}\n\nfunc (s *GetService) FetchSource(fetchSource bool) *GetService {\n\tif s.fsc == nil {\n\t\ts.fsc = NewFetchSourceContext(fetchSource)\n\t} else {\n\t\ts.fsc.SetFetchSource(fetchSource)\n\t}\n\treturn s\n}\n\nfunc (s *GetService) FetchSourceContext(fetchSourceContext *FetchSourceContext) *GetService {\n\ts.fsc = fetchSourceContext\n\treturn s\n}\n\n// Refresh the shard containing the document before performing the operation.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *GetService) Refresh(refresh string) *GetService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// Realtime specifies whether to perform the operation in realtime or search mode.\nfunc (s *GetService) Realtime(realtime bool) *GetService {\n\ts.realtime = &realtime\n\treturn s\n}\n\n// VersionType is the specific version type.\nfunc (s *GetService) VersionType(versionType string) *GetService {\n\ts.versionType = versionType\n\treturn s\n}\n\n// Version is an explicit version number for concurrency control.\nfunc (s *GetService) Version(version interface{}) *GetService {\n\ts.version = version\n\treturn s\n}\n\n// IgnoreErrorsOnGeneratedFields indicates whether to ignore fields that\n// are generated if the transaction log is accessed.\nfunc (s *GetService) IgnoreErrorsOnGeneratedFields(ignore bool) *GetService {\n\ts.ignoreErrorsOnGeneratedFields = &ignore\n\treturn s\n}\n\n// Validate checks if the operation is valid.\nfunc (s *GetService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif s.typ == \"\" {\n\t\tinvalid = append(invalid, \"Type\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *GetService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/{type}/{id}\", map[string]string{\n\t\t\"id\":    s.id,\n\t\t\"index\": s.index,\n\t\t\"type\":  s.typ,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.parent != \"\" {\n\t\tparams.Set(\"parent\", s.parent)\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif len(s.storedFields) > 0 {\n\t\tparams.Set(\"stored_fields\", strings.Join(s.storedFields, \",\"))\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Set(\"refresh\", s.refresh)\n\t}\n\tif s.version != nil {\n\t\tparams.Set(\"version\", fmt.Sprintf(\"%v\", s.version))\n\t}\n\tif s.versionType != \"\" {\n\t\tparams.Set(\"version_type\", s.versionType)\n\t}\n\tif s.realtime != nil {\n\t\tparams.Set(\"realtime\", fmt.Sprintf(\"%v\", *s.realtime))\n\t}\n\tif s.ignoreErrorsOnGeneratedFields != nil {\n\t\tparams.Add(\"ignore_errors_on_generated_fields\", fmt.Sprintf(\"%v\", *s.ignoreErrorsOnGeneratedFields))\n\t}\n\tif s.fsc != nil {\n\t\tfor k, values := range s.fsc.Query() {\n\t\t\tparams.Add(k, strings.Join(values, \",\"))\n\t\t}\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the operation.\nfunc (s *GetService) Do(ctx context.Context) (*GetResult, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(GetResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a get request.\n\n// GetResult is the outcome of GetService.Do.\ntype GetResult struct {\n\tIndex       string                 `json:\"_index\"`   // index meta field\n\tType        string                 `json:\"_type\"`    // type meta field\n\tId          string                 `json:\"_id\"`      // id meta field\n\tUid         string                 `json:\"_uid\"`     // uid meta field (see MapperService.java for all meta fields)\n\tRouting     string                 `json:\"_routing\"` // routing meta field\n\tParent      string                 `json:\"_parent\"`  // parent meta field\n\tVersion     *int64                 `json:\"_version\"` // version number, when Version is set to true in SearchService\n\tSeqNo       *int64                 `json:\"_seq_no\"`\n\tPrimaryTerm *int64                 `json:\"_primary_term\"`\n\tSource      json.RawMessage        `json:\"_source,omitempty\"`\n\tFound       bool                   `json:\"found,omitempty\"`\n\tFields      map[string]interface{} `json:\"fields,omitempty\"`\n\t//Error     string                 `json:\"error,omitempty\"` // used only in MultiGet\n\t// TODO double-check that MultiGet now returns details error information\n\tError *ErrorDetails `json:\"error,omitempty\"` // only used in MultiGet\n}\n"
  },
  {
    "path": "get_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGet(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Get document 1\n\tres, err := client.Get().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Found != true {\n\t\tt.Errorf(\"expected Found = true; got %v\", res.Found)\n\t}\n\tif res.Source == nil {\n\t\tt.Errorf(\"expected Source != nil; got %v\", res.Source)\n\t}\n\n\t// Get non existent document 99\n\tres, err = client.Get().Index(testIndexName).Id(\"99\").Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected error; got: %v\", err)\n\t}\n\tif !IsNotFound(err) {\n\t\tt.Errorf(\"expected NotFound error; got: %v\", err)\n\t}\n\tif res != nil {\n\t\tt.Errorf(\"expected no response; got: %v\", res)\n\t}\n}\n\nfunc TestGetWithSourceFiltering(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Get document 1, without source\n\tres, err := client.Get().Index(testIndexName).Id(\"1\").FetchSource(false).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Found != true {\n\t\tt.Errorf(\"expected Found = true; got %v\", res.Found)\n\t}\n\tif res.Source != nil {\n\t\tt.Errorf(\"expected Source == nil; got %v\", res.Source)\n\t}\n\n\t// Get document 1, exclude Message field\n\tfsc := NewFetchSourceContext(true).Exclude(\"message\")\n\tres, err = client.Get().Index(testIndexName).Id(\"1\").FetchSourceContext(fsc).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Found != true {\n\t\tt.Errorf(\"expected Found = true; got %v\", res.Found)\n\t}\n\tif res.Source == nil {\n\t\tt.Errorf(\"expected Source != nil; got %v\", res.Source)\n\t}\n\tvar tw tweet\n\terr = json.Unmarshal(res.Source, &tw)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif tw.User != \"olivere\" {\n\t\tt.Errorf(\"expected user %q; got: %q\", \"olivere\", tw.User)\n\t}\n\tif tw.Message != \"\" {\n\t\tt.Errorf(\"expected message %q; got: %q\", \"\", tw.Message)\n\t}\n}\n\nfunc TestGetWithFields(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Get document 1, specifying fields\n\tres, err := client.Get().Index(testIndexName).Id(\"1\").StoredFields(\"message\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Found != true {\n\t\tt.Errorf(\"expected Found = true; got: %v\", res.Found)\n\t}\n\n\t// We must NOT have the \"user\" field\n\t_, ok := res.Fields[\"user\"]\n\tif ok {\n\t\tt.Fatalf(\"expected no field %q in document\", \"user\")\n\t}\n\n\t// We must have the \"message\" field\n\tmessageField, ok := res.Fields[\"message\"]\n\tif !ok {\n\t\tt.Fatalf(\"expected field %q in document\", \"message\")\n\t}\n\n\t// Depending on the version of elasticsearch the message field will be returned\n\t// as a string or a slice of strings. This test works in both cases.\n\n\tmessageString, ok := messageField.(string)\n\tif !ok {\n\t\tmessageArray, ok := messageField.([]interface{})\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected field %q to be a string or a slice of strings; got: %T\", \"message\", messageField)\n\t\t} else {\n\t\t\tmessageString, ok = messageArray[0].(string)\n\t\t\tif !ok {\n\t\t\t\tt.Fatalf(\"expected field %q to be a string or a slice of strings; got: %T\", \"message\", messageField)\n\t\t\t}\n\t\t}\n\t}\n\n\tif messageString != tweet1.Message {\n\t\tt.Errorf(\"expected message %q; got: %q\", tweet1.Message, messageString)\n\t}\n}\n\nfunc TestGetValidate(t *testing.T) {\n\t// Mitigate against http://stackoverflow.com/questions/27491738/elasticsearch-go-index-failures-no-feature-for-name\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tif _, err := client.Get().Do(context.TODO()); err == nil {\n\t\tt.Fatal(\"expected Get to fail\")\n\t}\n\tif _, err := client.Get().Index(testIndexName).Do(context.TODO()); err == nil {\n\t\tt.Fatal(\"expected Get to fail\")\n\t}\n\tif _, err := client.Get().Do(context.TODO()); err == nil {\n\t\tt.Fatal(\"expected Get to fail\")\n\t}\n\tif _, err := client.Get().Id(\"1\").Do(context.TODO()); err == nil {\n\t\tt.Fatal(\"expected Get to fail\")\n\t}\n\tif _, err := client.Get().Index(testIndexName).Do(context.TODO()); err == nil {\n\t\tt.Fatal(\"expected Get to fail\")\n\t}\n\tif _, err := client.Get().Id(\"1\").Do(context.TODO()); err == nil {\n\t\tt.Fatal(\"expected Get to fail\")\n\t}\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/olivere/elastic/v7\n\ngo 1.17\n\nrequire (\n\tgithub.com/aws/aws-sdk-go v1.43.21\n\tgithub.com/fortytw2/leaktest v1.3.0\n\tgithub.com/google/go-cmp v0.5.7\n\tgithub.com/mailru/easyjson v0.7.7\n\tgithub.com/opentracing/opentracing-go v1.2.0\n\tgithub.com/pkg/errors v0.9.1\n\tgithub.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9\n\tgo.opencensus.io v0.23.0\n\tgo.opentelemetry.io/otel v1.5.0\n)\n\nrequire (\n\tgithub.com/go-logr/logr v1.2.2 // indirect\n\tgithub.com/go-logr/stdr v1.2.2 // indirect\n\tgithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect\n\tgithub.com/jmespath/go-jmespath v0.4.0 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/smartystreets/assertions v1.1.1 // indirect\n\tgithub.com/smartystreets/gunit v1.4.2 // indirect\n\tgo.opentelemetry.io/otel/trace v1.5.0 // indirect\n)\n"
  },
  {
    "path": "highlight.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// Highlight allows highlighting search results on one or more fields.\n// For details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-highlighting.html\ntype Highlight struct {\n\tfields                []*HighlighterField\n\ttagsSchema            *string\n\thighlightFilter       *bool\n\tfragmentSize          *int\n\tnumOfFragments        *int\n\tpreTags               []string\n\tpostTags              []string\n\torder                 *string\n\tencoder               *string\n\trequireFieldMatch     *bool\n\tmaxAnalyzedOffset     *int\n\tboundaryMaxScan       *int\n\tboundaryChars         *string\n\tboundaryScannerType   *string\n\tboundaryScannerLocale *string\n\thighlighterType       *string\n\tfragmenter            *string\n\thighlightQuery        Query\n\tnoMatchSize           *int\n\tphraseLimit           *int\n\toptions               map[string]interface{}\n\tforceSource           *bool\n\tuseExplicitFieldOrder bool\n}\n\nfunc NewHighlight() *Highlight {\n\thl := &Highlight{\n\t\toptions: make(map[string]interface{}),\n\t}\n\treturn hl\n}\n\nfunc (hl *Highlight) Fields(fields ...*HighlighterField) *Highlight {\n\thl.fields = append(hl.fields, fields...)\n\treturn hl\n}\n\nfunc (hl *Highlight) Field(name string) *Highlight {\n\tfield := NewHighlighterField(name)\n\thl.fields = append(hl.fields, field)\n\treturn hl\n}\n\nfunc (hl *Highlight) TagsSchema(schemaName string) *Highlight {\n\thl.tagsSchema = &schemaName\n\treturn hl\n}\n\nfunc (hl *Highlight) HighlightFilter(highlightFilter bool) *Highlight {\n\thl.highlightFilter = &highlightFilter\n\treturn hl\n}\n\nfunc (hl *Highlight) FragmentSize(fragmentSize int) *Highlight {\n\thl.fragmentSize = &fragmentSize\n\treturn hl\n}\n\nfunc (hl *Highlight) NumOfFragments(numOfFragments int) *Highlight {\n\thl.numOfFragments = &numOfFragments\n\treturn hl\n}\n\nfunc (hl *Highlight) Encoder(encoder string) *Highlight {\n\thl.encoder = &encoder\n\treturn hl\n}\n\nfunc (hl *Highlight) PreTags(preTags ...string) *Highlight {\n\thl.preTags = append(hl.preTags, preTags...)\n\treturn hl\n}\n\nfunc (hl *Highlight) PostTags(postTags ...string) *Highlight {\n\thl.postTags = append(hl.postTags, postTags...)\n\treturn hl\n}\n\nfunc (hl *Highlight) Order(order string) *Highlight {\n\thl.order = &order\n\treturn hl\n}\n\nfunc (hl *Highlight) RequireFieldMatch(requireFieldMatch bool) *Highlight {\n\thl.requireFieldMatch = &requireFieldMatch\n\treturn hl\n}\n\nfunc (hl *Highlight) MaxAnalyzedOffset(maxAnalyzedOffset int) *Highlight {\n\thl.maxAnalyzedOffset = &maxAnalyzedOffset\n\treturn hl\n}\n\nfunc (hl *Highlight) BoundaryMaxScan(boundaryMaxScan int) *Highlight {\n\thl.boundaryMaxScan = &boundaryMaxScan\n\treturn hl\n}\n\nfunc (hl *Highlight) BoundaryChars(boundaryChars string) *Highlight {\n\thl.boundaryChars = &boundaryChars\n\treturn hl\n}\n\nfunc (hl *Highlight) BoundaryScannerType(boundaryScannerType string) *Highlight {\n\thl.boundaryScannerType = &boundaryScannerType\n\treturn hl\n}\n\nfunc (hl *Highlight) BoundaryScannerLocale(boundaryScannerLocale string) *Highlight {\n\thl.boundaryScannerLocale = &boundaryScannerLocale\n\treturn hl\n}\n\nfunc (hl *Highlight) HighlighterType(highlighterType string) *Highlight {\n\thl.highlighterType = &highlighterType\n\treturn hl\n}\n\nfunc (hl *Highlight) Fragmenter(fragmenter string) *Highlight {\n\thl.fragmenter = &fragmenter\n\treturn hl\n}\n\nfunc (hl *Highlight) HighlightQuery(highlightQuery Query) *Highlight {\n\thl.highlightQuery = highlightQuery\n\treturn hl\n}\n\nfunc (hl *Highlight) NoMatchSize(noMatchSize int) *Highlight {\n\thl.noMatchSize = &noMatchSize\n\treturn hl\n}\n\nfunc (hl *Highlight) Options(options map[string]interface{}) *Highlight {\n\thl.options = options\n\treturn hl\n}\n\nfunc (hl *Highlight) ForceSource(forceSource bool) *Highlight {\n\thl.forceSource = &forceSource\n\treturn hl\n}\n\nfunc (hl *Highlight) UseExplicitFieldOrder(useExplicitFieldOrder bool) *Highlight {\n\thl.useExplicitFieldOrder = useExplicitFieldOrder\n\treturn hl\n}\n\n// Creates the query source for the bool query.\nfunc (hl *Highlight) Source() (interface{}, error) {\n\t// Returns the map inside of \"highlight\":\n\t// \"highlight\":{\n\t//   ... this ...\n\t// }\n\tsource := make(map[string]interface{})\n\tif hl.tagsSchema != nil {\n\t\tsource[\"tags_schema\"] = *hl.tagsSchema\n\t}\n\tif hl.preTags != nil && len(hl.preTags) > 0 {\n\t\tsource[\"pre_tags\"] = hl.preTags\n\t}\n\tif hl.postTags != nil && len(hl.postTags) > 0 {\n\t\tsource[\"post_tags\"] = hl.postTags\n\t}\n\tif hl.order != nil {\n\t\tsource[\"order\"] = *hl.order\n\t}\n\tif hl.highlightFilter != nil {\n\t\tsource[\"highlight_filter\"] = *hl.highlightFilter\n\t}\n\tif hl.fragmentSize != nil {\n\t\tsource[\"fragment_size\"] = *hl.fragmentSize\n\t}\n\tif hl.numOfFragments != nil {\n\t\tsource[\"number_of_fragments\"] = *hl.numOfFragments\n\t}\n\tif hl.encoder != nil {\n\t\tsource[\"encoder\"] = *hl.encoder\n\t}\n\tif hl.requireFieldMatch != nil {\n\t\tsource[\"require_field_match\"] = *hl.requireFieldMatch\n\t}\n\tif hl.maxAnalyzedOffset != nil {\n\t\tsource[\"max_analyzed_offset\"] = *hl.maxAnalyzedOffset\n\t}\n\tif hl.boundaryMaxScan != nil {\n\t\tsource[\"boundary_max_scan\"] = *hl.boundaryMaxScan\n\t}\n\tif hl.boundaryChars != nil {\n\t\tsource[\"boundary_chars\"] = *hl.boundaryChars\n\t}\n\tif hl.boundaryScannerType != nil {\n\t\tsource[\"boundary_scanner\"] = *hl.boundaryScannerType\n\t}\n\tif hl.boundaryScannerLocale != nil {\n\t\tsource[\"boundary_scanner_locale\"] = *hl.boundaryScannerLocale\n\t}\n\tif hl.highlighterType != nil {\n\t\tsource[\"type\"] = *hl.highlighterType\n\t}\n\tif hl.fragmenter != nil {\n\t\tsource[\"fragmenter\"] = *hl.fragmenter\n\t}\n\tif hl.highlightQuery != nil {\n\t\tsrc, err := hl.highlightQuery.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"highlight_query\"] = src\n\t}\n\tif hl.noMatchSize != nil {\n\t\tsource[\"no_match_size\"] = *hl.noMatchSize\n\t}\n\tif hl.phraseLimit != nil {\n\t\tsource[\"phrase_limit\"] = *hl.phraseLimit\n\t}\n\tif hl.options != nil && len(hl.options) > 0 {\n\t\tsource[\"options\"] = hl.options\n\t}\n\tif hl.forceSource != nil {\n\t\tsource[\"force_source\"] = *hl.forceSource\n\t}\n\n\tif hl.fields != nil && len(hl.fields) > 0 {\n\t\tif hl.useExplicitFieldOrder {\n\t\t\t// Use a slice for the fields\n\t\t\tvar fields []map[string]interface{}\n\t\t\tfor _, field := range hl.fields {\n\t\t\t\tsrc, err := field.Source()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tfmap := make(map[string]interface{})\n\t\t\t\tfmap[field.Name] = src\n\t\t\t\tfields = append(fields, fmap)\n\t\t\t}\n\t\t\tsource[\"fields\"] = fields\n\t\t} else {\n\t\t\t// Use a map for the fields\n\t\t\tfields := make(map[string]interface{})\n\t\t\tfor _, field := range hl.fields {\n\t\t\t\tsrc, err := field.Source()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tfields[field.Name] = src\n\t\t\t}\n\t\t\tsource[\"fields\"] = fields\n\t\t}\n\t}\n\n\treturn source, nil\n}\n\n// HighlighterField specifies a highlighted field.\ntype HighlighterField struct {\n\tName string\n\n\tpreTags           []string\n\tpostTags          []string\n\tfragmentSize      int\n\tfragmentOffset    int\n\tnumOfFragments    int\n\thighlightFilter   *bool\n\torder             *string\n\trequireFieldMatch *bool\n\tboundaryMaxScan   int\n\tboundaryChars     []rune\n\thighlighterType   *string\n\tfragmenter        *string\n\thighlightQuery    Query\n\tnoMatchSize       *int\n\tmatchedFields     []string\n\tphraseLimit       *int\n\toptions           map[string]interface{}\n\tforceSource       *bool\n\n\t/*\n\t\tName              string\n\t\tpreTags           []string\n\t\tpostTags          []string\n\t\tfragmentSize      int\n\t\tnumOfFragments    int\n\t\tfragmentOffset    int\n\t\thighlightFilter   *bool\n\t\torder             string\n\t\trequireFieldMatch *bool\n\t\tboundaryMaxScan   int\n\t\tboundaryChars     []rune\n\t\thighlighterType   string\n\t\tfragmenter        string\n\t\thighlightQuery    Query\n\t\tnoMatchSize       *int\n\t\tmatchedFields     []string\n\t\toptions           map[string]interface{}\n\t\tforceSource       *bool\n\t*/\n}\n\nfunc NewHighlighterField(name string) *HighlighterField {\n\treturn &HighlighterField{\n\t\tName:            name,\n\t\tpreTags:         make([]string, 0),\n\t\tpostTags:        make([]string, 0),\n\t\tfragmentSize:    -1,\n\t\tfragmentOffset:  -1,\n\t\tnumOfFragments:  -1,\n\t\tboundaryMaxScan: -1,\n\t\tboundaryChars:   make([]rune, 0),\n\t\tmatchedFields:   make([]string, 0),\n\t\toptions:         make(map[string]interface{}),\n\t}\n}\n\nfunc (f *HighlighterField) PreTags(preTags ...string) *HighlighterField {\n\tf.preTags = append(f.preTags, preTags...)\n\treturn f\n}\n\nfunc (f *HighlighterField) PostTags(postTags ...string) *HighlighterField {\n\tf.postTags = append(f.postTags, postTags...)\n\treturn f\n}\n\nfunc (f *HighlighterField) FragmentSize(fragmentSize int) *HighlighterField {\n\tf.fragmentSize = fragmentSize\n\treturn f\n}\n\nfunc (f *HighlighterField) FragmentOffset(fragmentOffset int) *HighlighterField {\n\tf.fragmentOffset = fragmentOffset\n\treturn f\n}\n\nfunc (f *HighlighterField) NumOfFragments(numOfFragments int) *HighlighterField {\n\tf.numOfFragments = numOfFragments\n\treturn f\n}\n\nfunc (f *HighlighterField) HighlightFilter(highlightFilter bool) *HighlighterField {\n\tf.highlightFilter = &highlightFilter\n\treturn f\n}\n\nfunc (f *HighlighterField) Order(order string) *HighlighterField {\n\tf.order = &order\n\treturn f\n}\n\nfunc (f *HighlighterField) RequireFieldMatch(requireFieldMatch bool) *HighlighterField {\n\tf.requireFieldMatch = &requireFieldMatch\n\treturn f\n}\n\nfunc (f *HighlighterField) BoundaryMaxScan(boundaryMaxScan int) *HighlighterField {\n\tf.boundaryMaxScan = boundaryMaxScan\n\treturn f\n}\n\nfunc (f *HighlighterField) BoundaryChars(boundaryChars ...rune) *HighlighterField {\n\tf.boundaryChars = append(f.boundaryChars, boundaryChars...)\n\treturn f\n}\n\nfunc (f *HighlighterField) HighlighterType(highlighterType string) *HighlighterField {\n\tf.highlighterType = &highlighterType\n\treturn f\n}\n\nfunc (f *HighlighterField) Fragmenter(fragmenter string) *HighlighterField {\n\tf.fragmenter = &fragmenter\n\treturn f\n}\n\nfunc (f *HighlighterField) HighlightQuery(highlightQuery Query) *HighlighterField {\n\tf.highlightQuery = highlightQuery\n\treturn f\n}\n\nfunc (f *HighlighterField) NoMatchSize(noMatchSize int) *HighlighterField {\n\tf.noMatchSize = &noMatchSize\n\treturn f\n}\n\nfunc (f *HighlighterField) Options(options map[string]interface{}) *HighlighterField {\n\tf.options = options\n\treturn f\n}\n\nfunc (f *HighlighterField) MatchedFields(matchedFields ...string) *HighlighterField {\n\tf.matchedFields = append(f.matchedFields, matchedFields...)\n\treturn f\n}\n\nfunc (f *HighlighterField) PhraseLimit(phraseLimit int) *HighlighterField {\n\tf.phraseLimit = &phraseLimit\n\treturn f\n}\n\nfunc (f *HighlighterField) ForceSource(forceSource bool) *HighlighterField {\n\tf.forceSource = &forceSource\n\treturn f\n}\n\nfunc (f *HighlighterField) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tif f.preTags != nil && len(f.preTags) > 0 {\n\t\tsource[\"pre_tags\"] = f.preTags\n\t}\n\tif f.postTags != nil && len(f.postTags) > 0 {\n\t\tsource[\"post_tags\"] = f.postTags\n\t}\n\tif f.fragmentSize != -1 {\n\t\tsource[\"fragment_size\"] = f.fragmentSize\n\t}\n\tif f.numOfFragments != -1 {\n\t\tsource[\"number_of_fragments\"] = f.numOfFragments\n\t}\n\tif f.fragmentOffset != -1 {\n\t\tsource[\"fragment_offset\"] = f.fragmentOffset\n\t}\n\tif f.highlightFilter != nil {\n\t\tsource[\"highlight_filter\"] = *f.highlightFilter\n\t}\n\tif f.order != nil {\n\t\tsource[\"order\"] = *f.order\n\t}\n\tif f.requireFieldMatch != nil {\n\t\tsource[\"require_field_match\"] = *f.requireFieldMatch\n\t}\n\tif f.boundaryMaxScan != -1 {\n\t\tsource[\"boundary_max_scan\"] = f.boundaryMaxScan\n\t}\n\tif f.boundaryChars != nil && len(f.boundaryChars) > 0 {\n\t\tsource[\"boundary_chars\"] = f.boundaryChars\n\t}\n\tif f.highlighterType != nil {\n\t\tsource[\"type\"] = *f.highlighterType\n\t}\n\tif f.fragmenter != nil {\n\t\tsource[\"fragmenter\"] = *f.fragmenter\n\t}\n\tif f.highlightQuery != nil {\n\t\tsrc, err := f.highlightQuery.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"highlight_query\"] = src\n\t}\n\tif f.noMatchSize != nil {\n\t\tsource[\"no_match_size\"] = *f.noMatchSize\n\t}\n\tif f.matchedFields != nil && len(f.matchedFields) > 0 {\n\t\tsource[\"matched_fields\"] = f.matchedFields\n\t}\n\tif f.phraseLimit != nil {\n\t\tsource[\"phrase_limit\"] = *f.phraseLimit\n\t}\n\tif f.options != nil && len(f.options) > 0 {\n\t\tsource[\"options\"] = f.options\n\t}\n\tif f.forceSource != nil {\n\t\tsource[\"force_source\"] = *f.forceSource\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "highlight_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestHighlighterField(t *testing.T) {\n\tfield := NewHighlighterField(\"grade\")\n\tsrc, err := field.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHighlighterFieldWithOptions(t *testing.T) {\n\tfield := NewHighlighterField(\"grade\").FragmentSize(2).NumOfFragments(1)\n\tsrc, err := field.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"fragment_size\":2,\"number_of_fragments\":1}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHighlightWithStringField(t *testing.T) {\n\tbuilder := NewHighlight().Field(\"grade\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"fields\":{\"grade\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHighlightWithFields(t *testing.T) {\n\tgradeField := NewHighlighterField(\"grade\")\n\tbuilder := NewHighlight().Fields(gradeField)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"fields\":{\"grade\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHighlightWithMultipleFields(t *testing.T) {\n\tgradeField := NewHighlighterField(\"grade\")\n\tcolorField := NewHighlighterField(\"color\")\n\tbuilder := NewHighlight().Fields(gradeField, colorField)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"fields\":{\"color\":{},\"grade\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHighlighterWithExplicitFieldOrder(t *testing.T) {\n\tgradeField := NewHighlighterField(\"grade\").FragmentSize(2)\n\tcolorField := NewHighlighterField(\"color\").FragmentSize(2).NumOfFragments(1)\n\tbuilder := NewHighlight().Fields(gradeField, colorField).UseExplicitFieldOrder(true)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"fields\":[{\"grade\":{\"fragment_size\":2}},{\"color\":{\"fragment_size\":2,\"number_of_fragments\":1}}]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHighlightWithBoundarySettings(t *testing.T) {\n\tbuilder := NewHighlight().\n\t\tBoundaryChars(\" \\t\\r\").\n\t\tBoundaryScannerType(\"word\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"boundary_chars\":\" \\t\\r\",\"boundary_scanner\":\"word\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHighlightWithTermQuery(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun to do.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Specify highlighter\n\thl := NewHighlight()\n\thl = hl.Fields(NewHighlighterField(\"message\"))\n\thl = hl.PreTags(\"<em>\").PostTags(\"</em>\")\n\n\t// Match all should return all documents\n\tquery := NewPrefixQuery(\"message\", \"golang\")\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tHighlight(hl).\n\t\tQuery(query).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Fatalf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 1 {\n\t\tt.Fatalf(\"expected SearchResult.TotalHits() = %d; got %d\", 1, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 1 {\n\t\tt.Fatalf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 1, len(searchResult.Hits.Hits))\n\t}\n\n\thit := searchResult.Hits.Hits[0]\n\tvar tw tweet\n\tif err := json.Unmarshal(hit.Source, &tw); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif hit.Highlight == nil || len(hit.Highlight) == 0 {\n\t\tt.Fatal(\"expected hit to have a highlight; got nil\")\n\t}\n\tif hl, found := hit.Highlight[\"message\"]; found {\n\t\tif len(hl) != 1 {\n\t\t\tt.Fatalf(\"expected to have one highlight for field \\\"message\\\"; got %d\", len(hl))\n\t\t}\n\t\texpected := \"Welcome to <em>Golang</em> and Elasticsearch.\"\n\t\tif hl[0] != expected {\n\t\t\tt.Errorf(\"expected to have highlight \\\"%s\\\"; got \\\"%s\\\"\", expected, hl[0])\n\t\t}\n\t} else {\n\t\tt.Fatal(\"expected to have a highlight on field \\\"message\\\"; got none\")\n\t}\n}\n"
  },
  {
    "path": "index.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndexService adds or updates a typed JSON document in a specified index,\n// making it searchable.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-index_.html\n// for details.\ntype IndexService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid                  string\n\tindex               string\n\ttyp                 string\n\tparent              string\n\trouting             string\n\ttimeout             string\n\ttimestamp           string\n\tttl                 string\n\tversion             interface{}\n\topType              string\n\tversionType         string\n\trefresh             string\n\twaitForActiveShards string\n\tpipeline            string\n\tifSeqNo             *int64\n\tifPrimaryTerm       *int64\n\tbodyJson            interface{}\n\tbodyString          string\n}\n\n// NewIndexService creates a new IndexService.\nfunc NewIndexService(client *Client) *IndexService {\n\treturn &IndexService{\n\t\tclient: client,\n\t\ttyp:    \"_doc\",\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndexService) Pretty(pretty bool) *IndexService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndexService) Human(human bool) *IndexService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndexService) ErrorTrace(errorTrace bool) *IndexService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndexService) FilterPath(filterPath ...string) *IndexService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndexService) Header(name string, value string) *IndexService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndexService) Headers(headers http.Header) *IndexService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is the document ID.\nfunc (s *IndexService) Id(id string) *IndexService {\n\ts.id = id\n\treturn s\n}\n\n// Index is the name of the index.\nfunc (s *IndexService) Index(index string) *IndexService {\n\ts.index = index\n\treturn s\n}\n\n// Type is the type of the document.\n//\n// Deprecated: Types are in the process of being removed.\nfunc (s *IndexService) Type(typ string) *IndexService {\n\ts.typ = typ\n\treturn s\n}\n\n// WaitForActiveShards sets the number of shard copies that must be active\n// before proceeding with the index operation. Defaults to 1, meaning the\n// primary shard only. Set to `all` for all shard copies, otherwise set to\n// any non-negative value less than or equal to the total number of copies\n// for the shard (number of replicas + 1).\nfunc (s *IndexService) WaitForActiveShards(waitForActiveShards string) *IndexService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// Pipeline specifies the pipeline id to preprocess incoming documents with.\nfunc (s *IndexService) Pipeline(pipeline string) *IndexService {\n\ts.pipeline = pipeline\n\treturn s\n}\n\n// Refresh the index after performing the operation.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *IndexService) Refresh(refresh string) *IndexService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// Ttl is an expiration time for the document.\nfunc (s *IndexService) Ttl(ttl string) *IndexService {\n\ts.ttl = ttl\n\treturn s\n}\n\n// TTL is an expiration time for the document (alias for Ttl).\nfunc (s *IndexService) TTL(ttl string) *IndexService {\n\ts.ttl = ttl\n\treturn s\n}\n\n// Version is an explicit version number for concurrency control.\nfunc (s *IndexService) Version(version interface{}) *IndexService {\n\ts.version = version\n\treturn s\n}\n\n// OpType is an explicit operation type, i.e. \"create\" or \"index\" (default).\nfunc (s *IndexService) OpType(opType string) *IndexService {\n\ts.opType = opType\n\treturn s\n}\n\n// Parent is the ID of the parent document.\nfunc (s *IndexService) Parent(parent string) *IndexService {\n\ts.parent = parent\n\treturn s\n}\n\n// Routing is a specific routing value.\nfunc (s *IndexService) Routing(routing string) *IndexService {\n\ts.routing = routing\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndexService) Timeout(timeout string) *IndexService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// Timestamp is an explicit timestamp for the document.\nfunc (s *IndexService) Timestamp(timestamp string) *IndexService {\n\ts.timestamp = timestamp\n\treturn s\n}\n\n// VersionType is a specific version type.\nfunc (s *IndexService) VersionType(versionType string) *IndexService {\n\ts.versionType = versionType\n\treturn s\n}\n\n// IfSeqNo indicates to only perform the index operation if the last\n// operation that has changed the document has the specified sequence number.\nfunc (s *IndexService) IfSeqNo(seqNo int64) *IndexService {\n\ts.ifSeqNo = &seqNo\n\treturn s\n}\n\n// IfPrimaryTerm indicates to only perform the index operation if the\n// last operation that has changed the document has the specified primary term.\nfunc (s *IndexService) IfPrimaryTerm(primaryTerm int64) *IndexService {\n\ts.ifPrimaryTerm = &primaryTerm\n\treturn s\n}\n\n// BodyJson is the document as a serializable JSON interface.\nfunc (s *IndexService) BodyJson(body interface{}) *IndexService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the document encoded as a string.\nfunc (s *IndexService) BodyString(body string) *IndexService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndexService) buildURL() (string, string, url.Values, error) {\n\tvar err error\n\tvar method, path string\n\n\tif s.id != \"\" {\n\t\t// Create document with manual id\n\t\tmethod = \"PUT\"\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/{id}\", map[string]string{\n\t\t\t\"id\":    s.id,\n\t\t\t\"index\": s.index,\n\t\t\t\"type\":  s.typ,\n\t\t})\n\t} else {\n\t\t// Automatic ID generation\n\t\t// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-index_.html#index-creation\n\t\tmethod = \"POST\"\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/\", map[string]string{\n\t\t\t\"index\": s.index,\n\t\t\t\"type\":  s.typ,\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Set(\"refresh\", s.refresh)\n\t}\n\tif s.opType != \"\" {\n\t\tparams.Set(\"op_type\", s.opType)\n\t}\n\tif s.parent != \"\" {\n\t\tparams.Set(\"parent\", s.parent)\n\t}\n\tif s.pipeline != \"\" {\n\t\tparams.Set(\"pipeline\", s.pipeline)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.timestamp != \"\" {\n\t\tparams.Set(\"timestamp\", s.timestamp)\n\t}\n\tif s.ttl != \"\" {\n\t\tparams.Set(\"ttl\", s.ttl)\n\t}\n\tif s.version != nil {\n\t\tparams.Set(\"version\", fmt.Sprintf(\"%v\", s.version))\n\t}\n\tif s.versionType != \"\" {\n\t\tparams.Set(\"version_type\", s.versionType)\n\t}\n\tif v := s.ifSeqNo; v != nil {\n\t\tparams.Set(\"if_seq_no\", fmt.Sprintf(\"%d\", *v))\n\t}\n\tif v := s.ifPrimaryTerm; v != nil {\n\t\tparams.Set(\"if_primary_term\", fmt.Sprintf(\"%d\", *v))\n\t}\n\treturn method, path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndexService) Validate() error {\n\tvar invalid []string\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif s.typ == \"\" {\n\t\tinvalid = append(invalid, \"Type\")\n\t}\n\tif s.bodyString == \"\" && s.bodyJson == nil {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndexService) Do(ctx context.Context) (*IndexResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tmethod, path, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  method,\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndexResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndexResponse is the result of indexing a document in Elasticsearch.\ntype IndexResponse struct {\n\tIndex         string      `json:\"_index,omitempty\"`\n\tType          string      `json:\"_type,omitempty\"`\n\tId            string      `json:\"_id,omitempty\"`\n\tVersion       int64       `json:\"_version,omitempty\"`\n\tResult        string      `json:\"result,omitempty\"`\n\tShards        *ShardsInfo `json:\"_shards,omitempty\"`\n\tSeqNo         int64       `json:\"_seq_no,omitempty\"`\n\tPrimaryTerm   int64       `json:\"_primary_term,omitempty\"`\n\tStatus        int         `json:\"status,omitempty\"`\n\tForcedRefresh bool        `json:\"forced_refresh,omitempty\"`\n}\n"
  },
  {
    "path": "index_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"testing\"\n)\n\nfunc TestIndexLifecycle(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\n\t// Add a document\n\tindexResult, err := client.Index().\n\t\tIndex(testIndexName).\n\t\tId(\"1\").\n\t\tBodyJson(&tweet1).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indexResult == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", indexResult)\n\t}\n\n\t// Exists\n\texists, err := client.Exists().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !exists {\n\t\tt.Errorf(\"expected exists %v; got %v\", true, exists)\n\t}\n\n\t// Get document\n\tgetResult, err := client.Get().\n\t\tIndex(testIndexName).\n\t\tId(\"1\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif getResult.Index != testIndexName {\n\t\tt.Errorf(\"expected GetResult.Index %q; got %q\", testIndexName, getResult.Index)\n\t}\n\tif getResult.Type != \"_doc\" {\n\t\tt.Errorf(\"expected GetResult.Type %q; got %q\", \"_doc\", getResult.Type)\n\t}\n\tif getResult.Id != \"1\" {\n\t\tt.Errorf(\"expected GetResult.Id %q; got %q\", \"1\", getResult.Id)\n\t}\n\tif getResult.Source == nil {\n\t\tt.Errorf(\"expected GetResult.Source to be != nil; got nil\")\n\t}\n\n\t// Decode the Source field\n\tvar tweetGot tweet\n\terr = json.Unmarshal(getResult.Source, &tweetGot)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif tweetGot.User != tweet1.User {\n\t\tt.Errorf(\"expected Tweet.User to be %q; got %q\", tweet1.User, tweetGot.User)\n\t}\n\tif tweetGot.Message != tweet1.Message {\n\t\tt.Errorf(\"expected Tweet.Message to be %q; got %q\", tweet1.Message, tweetGot.Message)\n\t}\n\n\t// Delete document again\n\tdeleteResult, err := client.Delete().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif deleteResult == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", deleteResult)\n\t}\n\n\t// Exists\n\texists, err = client.Exists().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif exists {\n\t\tt.Errorf(\"expected exists %v; got %v\", false, exists)\n\t}\n}\n\nfunc TestIndexLifecycleWithAutomaticIDGeneration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\n\t// Add a document\n\tindexResult, err := client.Index().\n\t\tIndex(testIndexName).\n\t\tBodyJson(&tweet1).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indexResult == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", indexResult)\n\t}\n\tif indexResult.Id == \"\" {\n\t\tt.Fatalf(\"expected Es to generate an automatic ID, got: %v\", indexResult.Id)\n\t}\n\tid := indexResult.Id\n\n\t// Exists\n\texists, err := client.Exists().Index(testIndexName).Id(id).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !exists {\n\t\tt.Errorf(\"expected exists %v; got %v\", true, exists)\n\t}\n\n\t// Get document\n\tgetResult, err := client.Get().\n\t\tIndex(testIndexName).\n\t\tId(id).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif getResult.Index != testIndexName {\n\t\tt.Errorf(\"expected GetResult.Index %q; got %q\", testIndexName, getResult.Index)\n\t}\n\tif getResult.Type != \"_doc\" {\n\t\tt.Errorf(\"expected GetResult.Type %q; got %q\", \"_doc\", getResult.Type)\n\t}\n\tif getResult.Id != id {\n\t\tt.Errorf(\"expected GetResult.Id %q; got %q\", id, getResult.Id)\n\t}\n\tif getResult.Source == nil {\n\t\tt.Errorf(\"expected GetResult.Source to be != nil; got nil\")\n\t}\n\n\t// Decode the Source field\n\tvar tweetGot tweet\n\terr = json.Unmarshal(getResult.Source, &tweetGot)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif tweetGot.User != tweet1.User {\n\t\tt.Errorf(\"expected Tweet.User to be %q; got %q\", tweet1.User, tweetGot.User)\n\t}\n\tif tweetGot.Message != tweet1.Message {\n\t\tt.Errorf(\"expected Tweet.Message to be %q; got %q\", tweet1.Message, tweetGot.Message)\n\t}\n\n\t// Delete document again\n\tdeleteResult, err := client.Delete().Index(testIndexName).Id(id).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif deleteResult == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", deleteResult)\n\t}\n\n\t// Exists\n\texists, err = client.Exists().Index(testIndexName).Id(id).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif exists {\n\t\tt.Errorf(\"expected exists %v; got %v\", false, exists)\n\t}\n}\n\nfunc TestIndexValidate(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttweet := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\n\t// No index name -> fail with error\n\tres, err := NewIndexService(client).Id(\"1\").BodyJson(&tweet).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected Index to fail without index name\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected result to be == nil; got: %v\", res)\n\t}\n}\n\nfunc TestIndexCreateExistsOpenCloseDelete(t *testing.T) {\n\t// TODO: Find out how to make these test robust\n\tt.Skip(\"test fails regularly with 409 (Conflict): \" +\n\t\t\"IndexPrimaryShardNotAllocatedException[[elastic-test] \" +\n\t\t\"primary not allocated post api... skipping\")\n\n\tclient := setupTestClient(t)\n\n\t// Create index\n\tcreateIndex, err := client.CreateIndex(testIndexName).Body(testMapping).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex == nil {\n\t\tt.Fatalf(\"expected response; got: %v\", createIndex)\n\t}\n\tif !createIndex.Acknowledged {\n\t\tt.Errorf(\"expected ack for creating index; got: %v\", createIndex.Acknowledged)\n\t}\n\n\t// Exists\n\tindexExists, err := client.IndexExists(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !indexExists {\n\t\tt.Fatalf(\"expected index exists=%v; got %v\", true, indexExists)\n\t}\n\n\t// Refresh\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Close index\n\tcloseIndex, err := client.CloseIndex(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif closeIndex == nil {\n\t\tt.Fatalf(\"expected response; got: %v\", closeIndex)\n\t}\n\tif !closeIndex.Acknowledged {\n\t\tt.Errorf(\"expected ack for closing index; got: %v\", closeIndex.Acknowledged)\n\t}\n\n\t// Open index\n\topenIndex, err := client.OpenIndex(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif openIndex == nil {\n\t\tt.Fatalf(\"expected response; got: %v\", openIndex)\n\t}\n\tif !openIndex.Acknowledged {\n\t\tt.Errorf(\"expected ack for opening index; got: %v\", openIndex.Acknowledged)\n\t}\n\n\t// Refresh\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Delete index\n\tdeleteIndex, err := client.DeleteIndex(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif deleteIndex == nil {\n\t\tt.Fatalf(\"expected response; got: %v\", deleteIndex)\n\t}\n\tif !deleteIndex.Acknowledged {\n\t\tt.Errorf(\"expected ack for deleting index; got %v\", deleteIndex.Acknowledged)\n\t}\n}\n\nfunc TestIndexOptimistic(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\ttw := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\n\t// Add a document\n\tdoc, err := client.Index().\n\t\tIndex(testIndexName).Id(\"1\").\n\t\tBodyJson(&tw).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif doc == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", doc)\n\t}\n\n\ttw.Retweets++\n\n\t// Index with seqNo != doc.SeqNo and primaryTerm != doc.PrimaryTerm\n\t_, err = client.Index().\n\t\tIndex(testIndexName).Id(doc.Id).\n\t\tIfSeqNo(doc.SeqNo + 1000).\n\t\tIfPrimaryTerm(doc.PrimaryTerm + 1000).\n\t\tBodyJson(&tw).\n\t\tDo(context.Background())\n\tif err == nil {\n\t\tt.Fatal(\"expected error, got nil\")\n\t}\n\tif !IsConflict(err) {\n\t\tt.Fatalf(\"expected conflict error, got %v (%T)\", err, err)\n\t}\n\n\t// Index with seqNo == doc.SeqNo and primaryTerm == doc.PrimaryTerm\n\tres, err := client.Index().\n\t\tIndex(testIndexName).Id(doc.Id).\n\t\tIfSeqNo(doc.SeqNo).\n\t\tIfPrimaryTerm(doc.PrimaryTerm).\n\t\tBodyJson(&tw).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response != nil\")\n\t}\n\tif want, have := res.SeqNo, doc.SeqNo; want == have {\n\t\tt.Fatalf(\"expected SeqNo to change (%d == %d)\", want, have)\n\t}\n}\n\nfunc TestIndexOnReadOnlyIndex(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\t//client := setupTestClientAndCreateIndexAndLog(t)\n\n\t// Change index to read-only\n\t{\n\t\t_, err := client.IndexPutSettings(testIndexName).\n\t\t\tBodyString(`{\n\t\t\t\t\"index\": {\n\t\t\t\t\t\"blocks\": {\n\t\t\t\t\t\t\"read_only_allow_delete\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}`).Pretty(true).Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"unable to set index into read-only mode: %v\", err)\n\t\t}\n\t}\n\n\t// Index something\n\ttweet := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\tresp, err := client.Index().\n\t\tIndex(testIndexName).Id(\"1\").\n\t\tBodyJson(tweet).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err == nil {\n\t\tt.Fatal(\"expected an error\")\n\t}\n\telasticErr, ok := err.(*Error)\n\tif !ok {\n\t\tt.Fatalf(\"expected an Error type, got %T\", err)\n\t}\n\tif want, have := http.StatusTooManyRequests, elasticErr.Status; want != have {\n\t\tt.Fatalf(\"expected HTTP status code %d, got %d\", want, have)\n\t}\n\tif resp != nil {\n\t\tt.Fatal(\"expected response to be nil\")\n\t}\n}\n"
  },
  {
    "path": "indices_analyze.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesAnalyzeService performs the analysis process on a text and returns\n// the tokens breakdown of the text.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-analyze.html\n// for detail.\ntype IndicesAnalyzeService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex       string\n\trequest     *IndicesAnalyzeRequest\n\tformat      string\n\tpreferLocal *bool\n\tbodyJson    interface{}\n\tbodyString  string\n}\n\n// NewIndicesAnalyzeService creates a new IndicesAnalyzeService.\nfunc NewIndicesAnalyzeService(client *Client) *IndicesAnalyzeService {\n\treturn &IndicesAnalyzeService{\n\t\tclient:  client,\n\t\trequest: new(IndicesAnalyzeRequest),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesAnalyzeService) Pretty(pretty bool) *IndicesAnalyzeService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesAnalyzeService) Human(human bool) *IndicesAnalyzeService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesAnalyzeService) ErrorTrace(errorTrace bool) *IndicesAnalyzeService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesAnalyzeService) FilterPath(filterPath ...string) *IndicesAnalyzeService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesAnalyzeService) Header(name string, value string) *IndicesAnalyzeService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesAnalyzeService) Headers(headers http.Header) *IndicesAnalyzeService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the index to scope the operation.\nfunc (s *IndicesAnalyzeService) Index(index string) *IndicesAnalyzeService {\n\ts.index = index\n\treturn s\n}\n\n// Format of the output.\nfunc (s *IndicesAnalyzeService) Format(format string) *IndicesAnalyzeService {\n\ts.format = format\n\treturn s\n}\n\n// PreferLocal, when true, specifies that a local shard should be used\n// if available. When false, a random shard is used (default: true).\nfunc (s *IndicesAnalyzeService) PreferLocal(preferLocal bool) *IndicesAnalyzeService {\n\ts.preferLocal = &preferLocal\n\treturn s\n}\n\n// Request passes the analyze request to use.\nfunc (s *IndicesAnalyzeService) Request(request *IndicesAnalyzeRequest) *IndicesAnalyzeService {\n\tif request == nil {\n\t\ts.request = new(IndicesAnalyzeRequest)\n\t} else {\n\t\ts.request = request\n\t}\n\treturn s\n}\n\n// Analyzer is the name of the analyzer to use.\nfunc (s *IndicesAnalyzeService) Analyzer(analyzer string) *IndicesAnalyzeService {\n\ts.request.Analyzer = analyzer\n\treturn s\n}\n\n// Attributes is a list of token attributes to output; this parameter works\n// only with explain=true.\nfunc (s *IndicesAnalyzeService) Attributes(attributes ...string) *IndicesAnalyzeService {\n\ts.request.Attributes = attributes\n\treturn s\n}\n\n// CharFilter is a list of character filters to use for the analysis.\nfunc (s *IndicesAnalyzeService) CharFilter(charFilter ...string) *IndicesAnalyzeService {\n\ts.request.CharFilter = charFilter\n\treturn s\n}\n\n// Explain, when true, outputs more advanced details (default: false).\nfunc (s *IndicesAnalyzeService) Explain(explain bool) *IndicesAnalyzeService {\n\ts.request.Explain = explain\n\treturn s\n}\n\n// Field specifies to use a specific analyzer configured for this field (instead of passing the analyzer name).\nfunc (s *IndicesAnalyzeService) Field(field string) *IndicesAnalyzeService {\n\ts.request.Field = field\n\treturn s\n}\n\n// Filter is a list of filters to use for the analysis.\nfunc (s *IndicesAnalyzeService) Filter(filter ...string) *IndicesAnalyzeService {\n\ts.request.Filter = filter\n\treturn s\n}\n\n// Text is the text on which the analysis should be performed (when request body is not used).\nfunc (s *IndicesAnalyzeService) Text(text ...string) *IndicesAnalyzeService {\n\ts.request.Text = text\n\treturn s\n}\n\n// Tokenizer is the name of the tokenizer to use for the analysis.\nfunc (s *IndicesAnalyzeService) Tokenizer(tokenizer string) *IndicesAnalyzeService {\n\ts.request.Tokenizer = tokenizer\n\treturn s\n}\n\n// BodyJson is the text on which the analysis should be performed.\nfunc (s *IndicesAnalyzeService) BodyJson(body interface{}) *IndicesAnalyzeService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the text on which the analysis should be performed.\nfunc (s *IndicesAnalyzeService) BodyString(body string) *IndicesAnalyzeService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesAnalyzeService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\n\tif s.index == \"\" {\n\t\tpath = \"/_analyze\"\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_analyze\", map[string]string{\n\t\t\t\"index\": s.index,\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.format != \"\" {\n\t\tparams.Set(\"format\", s.format)\n\t}\n\tif s.preferLocal != nil {\n\t\tparams.Set(\"prefer_local\", fmt.Sprintf(\"%v\", *s.preferLocal))\n\t}\n\n\treturn path, params, nil\n}\n\n// Do will execute the request with the given context.\nfunc (s *IndicesAnalyzeService) Do(ctx context.Context) (*IndicesAnalyzeResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else if s.bodyString != \"\" {\n\t\tbody = s.bodyString\n\t} else {\n\t\t// Request parameters are deprecated in 5.1.1, and we must use a JSON\n\t\t// structure in the body to pass the parameters.\n\t\t// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-analyze.html\n\t\tbody = s.request\n\t}\n\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tret := new(IndicesAnalyzeResponse)\n\tif err = s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn ret, nil\n}\n\nfunc (s *IndicesAnalyzeService) Validate() error {\n\tvar invalid []string\n\tif s.bodyJson == nil && s.bodyString == \"\" {\n\t\tif len(s.request.Text) == 0 {\n\t\t\tinvalid = append(invalid, \"Text\")\n\t\t}\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// IndicesAnalyzeRequest specifies the parameters of the analyze request.\ntype IndicesAnalyzeRequest struct {\n\tText       []string `json:\"text,omitempty\"`\n\tAnalyzer   string   `json:\"analyzer,omitempty\"`\n\tTokenizer  string   `json:\"tokenizer,omitempty\"`\n\tFilter     []string `json:\"filter,omitempty\"`\n\tCharFilter []string `json:\"char_filter,omitempty\"`\n\tField      string   `json:\"field,omitempty\"`\n\tExplain    bool     `json:\"explain,omitempty\"`\n\tAttributes []string `json:\"attributes,omitempty\"`\n}\n\ntype IndicesAnalyzeResponse struct {\n\tTokens []AnalyzeToken               `json:\"tokens\"` // json part for normal message\n\tDetail IndicesAnalyzeResponseDetail `json:\"detail\"` // json part for verbose message of explain request\n}\n\ntype AnalyzeTokenList struct {\n\tName   string         `json:\"name\"`\n\tTokens []AnalyzeToken `json:\"tokens,omitempty\"`\n}\n\ntype AnalyzeToken struct {\n\tToken          string `json:\"token\"`\n\tType           string `json:\"type\"` // e.g. \"<ALPHANUM>\"\n\tStartOffset    int    `json:\"start_offset\"`\n\tEndOffset      int    `json:\"end_offset\"`\n\tBytes          string `json:\"bytes\"` // e.g. \"[67 75 79]\"\n\tPosition       int    `json:\"position\"`\n\tPositionLength int    `json:\"positionLength\"` // seems to be wrong in 7.2+ (no snake_case), see https://github.com/elastic/elasticsearch/blob/7.2/server/src/main/java/org/elasticsearch/action/admin/indices/analyze/AnalyzeResponse.java\n\tTermFrequency  int    `json:\"termFrequency\"`\n\tKeyword        bool   `json:\"keyword\"`\n}\n\ntype CharFilteredText struct {\n\tName         string   `json:\"name\"`\n\tFilteredText []string `json:\"filtered_text\"`\n}\n\ntype IndicesAnalyzeResponseDetail struct {\n\tCustomAnalyzer bool                `json:\"custom_analyzer\"`\n\tAnalyzer       *AnalyzeTokenList   `json:\"analyzer,omitempty\"`\n\tCharfilters    []*CharFilteredText `json:\"charfilters,omitempty\"`\n\tTokenizer      *AnalyzeTokenList   `json:\"tokenizer,omitempty\"`\n\tTokenFilters   []*AnalyzeTokenList `json:\"tokenfilters,omitempty\"`\n}\n"
  },
  {
    "path": "indices_analyze_test.go",
    "content": "package elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesAnalyzeURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndex    string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"/_analyze\",\n\t\t},\n\t\t{\n\t\t\t\"tweets\",\n\t\t\t\"/tweets/_analyze\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.IndexAnalyze().Index(test.Index).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndicesAnalyze(t *testing.T) {\n\tclient := setupTestClient(t)\n\t// client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tres, err := client.IndexAnalyze().Text(\"hello hi guy\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error, got %v\", err)\n\t}\n\tif len(res.Tokens) != 3 {\n\t\tt.Fatalf(\"expected %d, got %d (%+v)\", 3, len(res.Tokens), res.Tokens)\n\t}\n}\n\nfunc TestIndicesAnalyzeDetail(t *testing.T) {\n\tclient := setupTestClient(t)\n\t// client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tres, err := client.IndexAnalyze().Text(\"hello hi guy\").Explain(true).Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error, got %v\", err)\n\t}\n\n\tif len(res.Detail.Analyzer.Tokens) != 3 {\n\t\tt.Fatalf(\"expected %d tokens, got %d (%+v)\", 3, len(res.Detail.Tokenizer.Tokens), res.Detail.Tokenizer.Tokens)\n\t}\n}\n\nfunc TestIndicesAnalyzeWithIndex(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t_, err := client.IndexAnalyze().Index(\"foo\").Text(\"hello hi guy\").Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatal(\"expected error, got nil\")\n\t}\n\tif want, have := \"elastic: Error 404 (Not Found): no such index [foo] [type=index_not_found_exception]\", err.Error(); want != have {\n\t\tt.Fatalf(\"expected error %q, got %q\", want, have)\n\t}\n}\n\nfunc TestIndicesAnalyzeValidate(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t_, err := client.IndexAnalyze().Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatal(\"expected error, got nil\")\n\t}\n\tif want, have := \"missing required fields: [Text]\", err.Error(); want != have {\n\t\tt.Fatalf(\"expected error %q, got %q\", want, have)\n\t}\n}\n"
  },
  {
    "path": "indices_clear_cache.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesClearCacheService allows to clear either all caches or specific cached associated\n// with one or more indices.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.6/indices-clearcache.html\n// for details.\ntype IndicesClearCacheService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n\tfieldData         *bool\n\tfields            string\n\tquery             *bool\n\trequest           *bool\n}\n\n// NewIndicesClearCacheService initializes a new instance of\n// IndicesClearCacheService.\nfunc NewIndicesClearCacheService(client *Client) *IndicesClearCacheService {\n\treturn &IndicesClearCacheService{client: client}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesClearCacheService) Pretty(pretty bool) *IndicesClearCacheService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesClearCacheService) Human(human bool) *IndicesClearCacheService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesClearCacheService) ErrorTrace(errorTrace bool) *IndicesClearCacheService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesClearCacheService) FilterPath(filterPath ...string) *IndicesClearCacheService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesClearCacheService) Header(name string, value string) *IndicesClearCacheService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesClearCacheService) Headers(headers http.Header) *IndicesClearCacheService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the comma-separated list or wildcard expression of index names used to clear cache.\nfunc (s *IndicesClearCacheService) Index(indices ...string) *IndicesClearCacheService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesClearCacheService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesClearCacheService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes `_all` string or when no indices\n// have been specified).\nfunc (s *IndicesClearCacheService) AllowNoIndices(allowNoIndices bool) *IndicesClearCacheService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *IndicesClearCacheService) ExpandWildcards(expandWildcards string) *IndicesClearCacheService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// FieldData indicates whether to clear the fields cache.\n// Use the fields parameter to clear the cache of specific fields only.\nfunc (s *IndicesClearCacheService) FieldData(fieldData bool) *IndicesClearCacheService {\n\ts.fieldData = &fieldData\n\treturn s\n}\n\n// Fields indicates comma-separated list of field names used to limit the fielddata parameter.\n// Defaults to all fields.\nfunc (s *IndicesClearCacheService) Fields(fields string) *IndicesClearCacheService {\n\ts.fields = fields\n\treturn s\n}\n\n// Query indicates whether to clear only query cache.\nfunc (s *IndicesClearCacheService) Query(queryCache bool) *IndicesClearCacheService {\n\ts.query = &queryCache\n\treturn s\n}\n\n// Request indicates whether to clear only request cache.\nfunc (s *IndicesClearCacheService) Request(requestCache bool) *IndicesClearCacheService {\n\ts.request = &requestCache\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesClearCacheService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar path string\n\tvar err error\n\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_cache/clear\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_cache/clear\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.allowNoIndices; v != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprint(*v))\n\t}\n\tif v := s.expandWildcards; v != \"\" {\n\t\tparams.Set(\"expand_wildcards\", v)\n\t}\n\tif v := s.ignoreUnavailable; v != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*v))\n\t}\n\tif len(s.index) > 0 {\n\t\tparams.Set(\"index\", fmt.Sprintf(\"%v\", s.index))\n\t}\n\tif v := s.ignoreUnavailable; v != nil {\n\t\tparams.Set(\"fielddata\", fmt.Sprint(*v))\n\t}\n\tif len(s.fields) > 0 {\n\t\tparams.Set(\"fields\", fmt.Sprintf(\"%v\", s.fields))\n\t}\n\tif v := s.query; v != nil {\n\t\tparams.Set(\"query\", fmt.Sprint(*v))\n\t}\n\tif s.request != nil {\n\t\tparams.Set(\"request\", fmt.Sprintf(\"%v\", *s.request))\n\t}\n\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesClearCacheService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesClearCacheService) Do(ctx context.Context) (*IndicesClearCacheResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesClearCacheResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesClearCacheResponse is the response of IndicesClearCacheService.Do.\ntype IndicesClearCacheResponse struct {\n\tShards *ShardsInfo `json:\"_shards\"`\n}\n"
  },
  {
    "path": "indices_clear_cache_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesClearCache(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tres, err := client.ClearCache().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatalf(\"expected ClearCache to succeed, got: %v\", err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected result to be != nil; got: %v\", res)\n\t}\n}\n\nfunc TestIndicesClearCacheBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t\"/_cache/clear\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t\"/index1/_cache/clear\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t\"/index1%2Cindex2/_cache/clear\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.ClearCache().Index(test.Indices...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_close.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesCloseService closes an index.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-open-close.html\n// for details.\ntype IndicesCloseService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             string\n\ttimeout           string\n\tmasterTimeout     string\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n}\n\n// NewIndicesCloseService creates and initializes a new IndicesCloseService.\nfunc NewIndicesCloseService(client *Client) *IndicesCloseService {\n\treturn &IndicesCloseService{client: client}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesCloseService) Pretty(pretty bool) *IndicesCloseService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesCloseService) Human(human bool) *IndicesCloseService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesCloseService) ErrorTrace(errorTrace bool) *IndicesCloseService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesCloseService) FilterPath(filterPath ...string) *IndicesCloseService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesCloseService) Header(name string, value string) *IndicesCloseService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesCloseService) Headers(headers http.Header) *IndicesCloseService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the index to close.\nfunc (s *IndicesCloseService) Index(index string) *IndicesCloseService {\n\ts.index = index\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndicesCloseService) Timeout(timeout string) *IndicesCloseService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesCloseService) MasterTimeout(masterTimeout string) *IndicesCloseService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesCloseService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesCloseService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified).\nfunc (s *IndicesCloseService) AllowNoIndices(allowNoIndices bool) *IndicesCloseService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *IndicesCloseService) ExpandWildcards(expandWildcards string) *IndicesCloseService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesCloseService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/_close\", map[string]string{\n\t\t\"index\": s.index,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesCloseService) Validate() error {\n\tvar invalid []string\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesCloseService) Do(ctx context.Context) (*IndicesCloseResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesCloseResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesCloseResponse is the response of IndicesCloseService.Do.\ntype IndicesCloseResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_close_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\n// TODO(oe): Find out why this test fails on Travis CI.\n/*\nfunc TestIndicesOpenAndClose(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// Create index\n\tcreateIndex, err := client.CreateIndex(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !createIndex.Acknowledged {\n\t\tt.Errorf(\"expected CreateIndexResult.Acknowledged %v; got %v\", true, createIndex.Acknowledged)\n\t}\n\tdefer func() {\n\t\t// Delete index\n\t\tdeleteIndex, err := client.DeleteIndex(testIndexName).Do(context.TODO())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif !deleteIndex.Acknowledged {\n\t\t\tt.Errorf(\"expected DeleteIndexResult.Acknowledged %v; got %v\", true, deleteIndex.Acknowledged)\n\t\t}\n\t}()\n\n\twaitForYellow := func() {\n\t\t// Wait for status yellow\n\t\tres, err := client.ClusterHealth().WaitForStatus(\"yellow\").Timeout(\"15s\").Do(context.TODO())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res != nil && res.TimedOut {\n\t\t\tt.Fatalf(\"cluster time out waiting for status %q\", \"yellow\")\n\t\t}\n\t}\n\n\t// Wait for cluster\n\twaitForYellow()\n\n\t// Close index\n\tcresp, err := client.CloseIndex(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !cresp.Acknowledged {\n\t\tt.Fatalf(\"expected close index of %q to be acknowledged\\n\", testIndexName)\n\t}\n\n\t// Wait for cluster\n\twaitForYellow()\n\n\t// Open index again\n\toresp, err := client.OpenIndex(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !oresp.Acknowledged {\n\t\tt.Fatalf(\"expected open index of %q to be acknowledged\\n\", testIndexName)\n\t}\n}\n*/\n\nfunc TestIndicesCloseValidate(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// No index name -> fail with error\n\tres, err := NewIndicesCloseService(client).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected IndicesClose to fail without index name\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected result to be == nil; got: %v\", res)\n\t}\n}\n"
  },
  {
    "path": "indices_component_templates_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestComponentTemplatesLifecycle(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tconst templateName = \"template_1\"\n\n\t// Always make sure the component template is deleted\n\tdefer func() {\n\t\t_, _ = client.IndexDeleteComponentTemplate(templateName).Pretty(true).Do(context.Background())\n\t}()\n\n\t// Create an component template\n\t{\n\t\tresp, err := client.IndexPutComponentTemplate(templateName).Pretty(true).BodyString(`{\n\t\t\t\"template\": {\n\t\t\t\t\"settings\": {\n\t\t\t\t\t\"number_of_shards\": 2,\n\t\t\t\t\t\"number_of_replicas\": 0\n\t\t\t\t},\n\t\t\t\t\"mappings\": {\n\t\t\t\t\t\"_source\": { \"enabled\": true }\n\t\t\t\t}\n\t\t\t}\n\t\t}`).Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected to successfully create component template, got %v\", err)\n\t\t}\n\t\tif resp == nil {\n\t\t\tt.Fatal(\"expected response on creating component template\")\n\t\t}\n\t\tif want, have := true, resp.Acknowledged; want != have {\n\t\t\tt.Errorf(\"expected Acknowledged=%v, got %v\", want, have)\n\t\t}\n\t}\n\n\t// Get the component template\n\t{\n\t\tresp, err := client.IndexGetComponentTemplate(templateName).Pretty(true).Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected to successfully get component template, got %v\", err)\n\t\t}\n\t\tif resp == nil {\n\t\t\tt.Fatal(\"expected response on getting component template\")\n\t\t}\n\t}\n\n\t// Delete the component template\n\t{\n\t\tresp, err := client.IndexDeleteComponentTemplate(templateName).Pretty(true).Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected to successfully delete component template, got %v\", err)\n\t\t}\n\t\tif resp == nil {\n\t\t\tt.Fatal(\"expected response on deleting component template\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_create.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesCreateService creates a new index.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-create-index.html\n// for details.\ntype IndicesCreateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex           string\n\ttimeout         string\n\tmasterTimeout   string\n\tincludeTypeName *bool\n\tbodyJson        interface{}\n\tbodyString      string\n}\n\n// NewIndicesCreateService returns a new IndicesCreateService.\nfunc NewIndicesCreateService(client *Client) *IndicesCreateService {\n\treturn &IndicesCreateService{client: client}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesCreateService) Pretty(pretty bool) *IndicesCreateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesCreateService) Human(human bool) *IndicesCreateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesCreateService) ErrorTrace(errorTrace bool) *IndicesCreateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesCreateService) FilterPath(filterPath ...string) *IndicesCreateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesCreateService) Header(name string, value string) *IndicesCreateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesCreateService) Headers(headers http.Header) *IndicesCreateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the index to create.\nfunc (s *IndicesCreateService) Index(index string) *IndicesCreateService {\n\ts.index = index\n\treturn s\n}\n\n// Timeout the explicit operation timeout, e.g. \"5s\".\nfunc (s *IndicesCreateService) Timeout(timeout string) *IndicesCreateService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesCreateService) MasterTimeout(masterTimeout string) *IndicesCreateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IncludeTypeName indicates whether a type should be expected in the body of the mappings.\nfunc (s *IndicesCreateService) IncludeTypeName(includeTypeName bool) *IndicesCreateService {\n\ts.includeTypeName = &includeTypeName\n\treturn s\n}\n\n// Body specifies the configuration of the index as a string.\n// It is an alias for BodyString.\nfunc (s *IndicesCreateService) Body(body string) *IndicesCreateService {\n\ts.bodyString = body\n\treturn s\n}\n\n// BodyString specifies the configuration of the index as a string.\nfunc (s *IndicesCreateService) BodyString(body string) *IndicesCreateService {\n\ts.bodyString = body\n\treturn s\n}\n\n// BodyJson specifies the configuration of the index. The interface{} will\n// be serializes as a JSON document, so use a map[string]interface{}.\nfunc (s *IndicesCreateService) BodyJson(body interface{}) *IndicesCreateService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// Do executes the operation.\nfunc (s *IndicesCreateService) Do(ctx context.Context) (*IndicesCreateResult, error) {\n\tif s.index == \"\" {\n\t\treturn nil, errors.New(\"missing index name\")\n\t}\n\n\t// Build url\n\tpath, err := uritemplates.Expand(\"/{index}\", map[string]string{\n\t\t\"index\": s.index,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif v := s.includeTypeName; v != nil {\n\t\tparams.Set(\"include_type_name\", fmt.Sprint(*v))\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tret := new(IndicesCreateResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a create index request.\n\n// IndicesCreateResult is the outcome of creating a new index.\ntype IndicesCreateResult struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_create_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesLifecycle(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// Create index\n\tcreateIndex, err := client.CreateIndex(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !createIndex.Acknowledged {\n\t\tt.Errorf(\"expected IndicesCreateResult.Acknowledged %v; got %v\", true, createIndex.Acknowledged)\n\t}\n\n\t// Check if index exists\n\tindexExists, err := client.IndexExists(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !indexExists {\n\t\tt.Fatalf(\"index %s should exist, but doesn't\\n\", testIndexName)\n\t}\n\n\t// Delete index\n\tdeleteIndex, err := client.DeleteIndex(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !deleteIndex.Acknowledged {\n\t\tt.Errorf(\"expected DeleteIndexResult.Acknowledged %v; got %v\", true, deleteIndex.Acknowledged)\n\t}\n\n\t// Check if index exists\n\tindexExists, err = client.IndexExists(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indexExists {\n\t\tt.Fatalf(\"index %s should not exist, but does\\n\", testIndexName)\n\t}\n}\n\nfunc TestIndicesCreateValidate(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// No index name -> fail with error\n\tres, err := NewIndicesCreateService(client).Body(testMapping).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected IndicesCreate to fail without index name\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected result to be == nil; got: %v\", res)\n\t}\n}\n"
  },
  {
    "path": "indices_delete.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesDeleteService allows to delete existing indices.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-delete-index.html\n// for details.\ntype IndicesDeleteService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\ttimeout           string\n\tmasterTimeout     string\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n}\n\n// NewIndicesDeleteService creates and initializes a new IndicesDeleteService.\nfunc NewIndicesDeleteService(client *Client) *IndicesDeleteService {\n\treturn &IndicesDeleteService{\n\t\tclient: client,\n\t\tindex:  make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesDeleteService) Pretty(pretty bool) *IndicesDeleteService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesDeleteService) Human(human bool) *IndicesDeleteService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesDeleteService) ErrorTrace(errorTrace bool) *IndicesDeleteService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesDeleteService) FilterPath(filterPath ...string) *IndicesDeleteService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesDeleteService) Header(name string, value string) *IndicesDeleteService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesDeleteService) Headers(headers http.Header) *IndicesDeleteService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index adds the list of indices to delete.\n// Use `_all` or `*` string to delete all indices.\nfunc (s *IndicesDeleteService) Index(index []string) *IndicesDeleteService {\n\ts.index = index\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndicesDeleteService) Timeout(timeout string) *IndicesDeleteService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesDeleteService) MasterTimeout(masterTimeout string) *IndicesDeleteService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether to ignore unavailable indexes (default: false).\nfunc (s *IndicesDeleteService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesDeleteService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard expression\n// resolves to no concrete indices (default: false).\nfunc (s *IndicesDeleteService) AllowNoIndices(allowNoIndices bool) *IndicesDeleteService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether wildcard expressions should get\n// expanded to open or closed indices (default: open).\nfunc (s *IndicesDeleteService) ExpandWildcards(expandWildcards string) *IndicesDeleteService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesDeleteService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}\", map[string]string{\n\t\t\"index\": strings.Join(s.index, \",\"),\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesDeleteService) Validate() error {\n\tvar invalid []string\n\tif len(s.index) == 0 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesDeleteService) Do(ctx context.Context) (*IndicesDeleteResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesDeleteResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a delete index request.\n\n// IndicesDeleteResponse is the response of IndicesDeleteService.Do.\ntype IndicesDeleteResponse struct {\n\tAcknowledged bool `json:\"acknowledged\"`\n}\n"
  },
  {
    "path": "indices_delete_component_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesDeleteComponentTemplateService deletes component templates.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-delete-component-template.html\n// for more details.\ntype IndicesDeleteComponentTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname          string\n\ttimeout       string\n\tmasterTimeout string\n}\n\n// NewIndicesDeleteComponentTemplateService creates a new IndicesDeleteComponentTemplateService.\nfunc NewIndicesDeleteComponentTemplateService(client *Client) *IndicesDeleteComponentTemplateService {\n\treturn &IndicesDeleteComponentTemplateService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesDeleteComponentTemplateService) Pretty(pretty bool) *IndicesDeleteComponentTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesDeleteComponentTemplateService) Human(human bool) *IndicesDeleteComponentTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesDeleteComponentTemplateService) ErrorTrace(errorTrace bool) *IndicesDeleteComponentTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesDeleteComponentTemplateService) FilterPath(filterPath ...string) *IndicesDeleteComponentTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesDeleteComponentTemplateService) Header(name string, value string) *IndicesDeleteComponentTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesDeleteComponentTemplateService) Headers(headers http.Header) *IndicesDeleteComponentTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the template.\nfunc (s *IndicesDeleteComponentTemplateService) Name(name string) *IndicesDeleteComponentTemplateService {\n\ts.name = name\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndicesDeleteComponentTemplateService) Timeout(timeout string) *IndicesDeleteComponentTemplateService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesDeleteComponentTemplateService) MasterTimeout(masterTimeout string) *IndicesDeleteComponentTemplateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesDeleteComponentTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_component_template/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesDeleteComponentTemplateService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesDeleteComponentTemplateService) Do(ctx context.Context) (*IndicesDeleteComponentTemplateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesDeleteComponentTemplateResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesDeleteComponentTemplateResponse is the response of IndicesDeleteComponentTemplateService.Do.\ntype IndicesDeleteComponentTemplateResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_delete_index_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesDeleteIndexTemplateService deletes index templates.\n//\n// Index templates have changed during in 7.8 update of Elasticsearch.\n// This service implements the new version (7.8 or later). If you want\n// the old version, please use the IndicesDeleteTemplateService.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-delete-template.html\n// for more details.\ntype IndicesDeleteIndexTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname          string\n\ttimeout       string\n\tmasterTimeout string\n}\n\n// NewIndicesDeleteIndexTemplateService creates a new IndicesDeleteIndexTemplateService.\nfunc NewIndicesDeleteIndexTemplateService(client *Client) *IndicesDeleteIndexTemplateService {\n\treturn &IndicesDeleteIndexTemplateService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesDeleteIndexTemplateService) Pretty(pretty bool) *IndicesDeleteIndexTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesDeleteIndexTemplateService) Human(human bool) *IndicesDeleteIndexTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesDeleteIndexTemplateService) ErrorTrace(errorTrace bool) *IndicesDeleteIndexTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesDeleteIndexTemplateService) FilterPath(filterPath ...string) *IndicesDeleteIndexTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesDeleteIndexTemplateService) Header(name string, value string) *IndicesDeleteIndexTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesDeleteIndexTemplateService) Headers(headers http.Header) *IndicesDeleteIndexTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the template.\nfunc (s *IndicesDeleteIndexTemplateService) Name(name string) *IndicesDeleteIndexTemplateService {\n\ts.name = name\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndicesDeleteIndexTemplateService) Timeout(timeout string) *IndicesDeleteIndexTemplateService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesDeleteIndexTemplateService) MasterTimeout(masterTimeout string) *IndicesDeleteIndexTemplateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesDeleteIndexTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_index_template/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesDeleteIndexTemplateService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesDeleteIndexTemplateService) Do(ctx context.Context) (*IndicesDeleteIndexTemplateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesDeleteIndexTemplateResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesDeleteIndexTemplateResponse is the response of IndicesDeleteIndexTemplateService.Do.\ntype IndicesDeleteIndexTemplateResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_delete_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesDeleteIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tbefore, err := client.IndexNames()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.DeleteIndex(testIndexName, testIndexNameEmpty).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tafter, err := client.IndexNames()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif want, have := len(after), len(before)-2; want != have {\n\t\tt.Fatalf(\"expected %d indices, got %d\", want, have)\n\t}\n}\n"
  },
  {
    "path": "indices_delete_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesDeleteTemplateService deletes templates.\n//\n// Index templates have changed during in 7.8 update of Elasticsearch.\n// This service implements the legacy version (7.7 or lower). If you want\n// the new version, please use the IndicesDeleteIndexTemplateService.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-delete-template-v1.html\n// for more details.\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\ntype IndicesDeleteTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname          string\n\ttimeout       string\n\tmasterTimeout string\n}\n\n// NewIndicesDeleteTemplateService creates a new IndicesDeleteTemplateService.\nfunc NewIndicesDeleteTemplateService(client *Client) *IndicesDeleteTemplateService {\n\treturn &IndicesDeleteTemplateService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesDeleteTemplateService) Pretty(pretty bool) *IndicesDeleteTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesDeleteTemplateService) Human(human bool) *IndicesDeleteTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesDeleteTemplateService) ErrorTrace(errorTrace bool) *IndicesDeleteTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesDeleteTemplateService) FilterPath(filterPath ...string) *IndicesDeleteTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesDeleteTemplateService) Header(name string, value string) *IndicesDeleteTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesDeleteTemplateService) Headers(headers http.Header) *IndicesDeleteTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the template.\nfunc (s *IndicesDeleteTemplateService) Name(name string) *IndicesDeleteTemplateService {\n\ts.name = name\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndicesDeleteTemplateService) Timeout(timeout string) *IndicesDeleteTemplateService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesDeleteTemplateService) MasterTimeout(masterTimeout string) *IndicesDeleteTemplateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesDeleteTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_template/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesDeleteTemplateService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\nfunc (s *IndicesDeleteTemplateService) Do(ctx context.Context) (*IndicesDeleteTemplateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesDeleteTemplateResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesDeleteTemplateResponse is the response of IndicesDeleteTemplateService.Do.\ntype IndicesDeleteTemplateResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_delete_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesDeleteValidate(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// No index name -> fail with error\n\tres, err := NewIndicesDeleteService(client).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected IndicesDelete to fail without index name\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected result to be == nil; got: %v\", res)\n\t}\n}\n"
  },
  {
    "path": "indices_exists.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesExistsService checks if an index or indices exist or not.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-exists.html\n// for details.\ntype IndicesExistsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n\tlocal             *bool\n}\n\n// NewIndicesExistsService creates and initializes a new IndicesExistsService.\nfunc NewIndicesExistsService(client *Client) *IndicesExistsService {\n\treturn &IndicesExistsService{\n\t\tclient: client,\n\t\tindex:  make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesExistsService) Pretty(pretty bool) *IndicesExistsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesExistsService) Human(human bool) *IndicesExistsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesExistsService) ErrorTrace(errorTrace bool) *IndicesExistsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesExistsService) FilterPath(filterPath ...string) *IndicesExistsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesExistsService) Header(name string, value string) *IndicesExistsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesExistsService) Headers(headers http.Header) *IndicesExistsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of one or more indices to check.\nfunc (s *IndicesExistsService) Index(index []string) *IndicesExistsService {\n\ts.index = index\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices expression\n// resolves into no concrete indices. (This includes `_all` string or\n// when no indices have been specified).\nfunc (s *IndicesExistsService) AllowNoIndices(allowNoIndices bool) *IndicesExistsService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *IndicesExistsService) ExpandWildcards(expandWildcards string) *IndicesExistsService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// Local, when set, returns local information and does not retrieve the state\n// from master node (default: false).\nfunc (s *IndicesExistsService) Local(local bool) *IndicesExistsService {\n\ts.local = &local\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesExistsService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesExistsService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesExistsService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}\", map[string]string{\n\t\t\"index\": strings.Join(s.index, \",\"),\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesExistsService) Validate() error {\n\tvar invalid []string\n\tif len(s.index) == 0 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesExistsService) Do(ctx context.Context) (bool, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn false, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:       \"HEAD\",\n\t\tPath:         path,\n\t\tParams:       params,\n\t\tIgnoreErrors: []int{404},\n\t\tHeaders:      s.headers,\n\t})\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\t// Return operation response\n\tswitch res.StatusCode {\n\tcase http.StatusOK:\n\t\treturn true, nil\n\tcase http.StatusNotFound:\n\t\treturn false, nil\n\tdefault:\n\t\treturn false, fmt.Errorf(\"elastic: got HTTP code %d when it should have been either 200 or 404\", res.StatusCode)\n\t}\n}\n"
  },
  {
    "path": "indices_exists_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesExistsTemplateService checks if a given template exists.\n// See http://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-templates.html#indices-templates-exists\n// for documentation.\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\ntype IndicesExistsTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname          string\n\tlocal         *bool\n\tmasterTimeout string\n}\n\n// NewIndicesExistsTemplateService creates a new IndicesExistsTemplateService.\nfunc NewIndicesExistsTemplateService(client *Client) *IndicesExistsTemplateService {\n\treturn &IndicesExistsTemplateService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesExistsTemplateService) Pretty(pretty bool) *IndicesExistsTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesExistsTemplateService) Human(human bool) *IndicesExistsTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesExistsTemplateService) ErrorTrace(errorTrace bool) *IndicesExistsTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesExistsTemplateService) FilterPath(filterPath ...string) *IndicesExistsTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesExistsTemplateService) Header(name string, value string) *IndicesExistsTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesExistsTemplateService) Headers(headers http.Header) *IndicesExistsTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the template.\nfunc (s *IndicesExistsTemplateService) Name(name string) *IndicesExistsTemplateService {\n\ts.name = name\n\treturn s\n}\n\n// Local indicates whether to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *IndicesExistsTemplateService) Local(local bool) *IndicesExistsTemplateService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesExistsTemplateService) MasterTimeout(masterTimeout string) *IndicesExistsTemplateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesExistsTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_template/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*s.local))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesExistsTemplateService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\nfunc (s *IndicesExistsTemplateService) Do(ctx context.Context) (bool, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn false, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:       \"HEAD\",\n\t\tPath:         path,\n\t\tParams:       params,\n\t\tIgnoreErrors: []int{404},\n\t\tHeaders:      s.headers,\n\t})\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\t// Return operation response\n\tswitch res.StatusCode {\n\tcase http.StatusOK:\n\t\treturn true, nil\n\tcase http.StatusNotFound:\n\t\treturn false, nil\n\tdefault:\n\t\treturn false, fmt.Errorf(\"elastic: got HTTP code %d when it should have been either 200 or 404\", res.StatusCode)\n\t}\n}\n"
  },
  {
    "path": "indices_exists_template_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndexExistsTemplate(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttmpl := `{\n\t\"index_patterns\":[\"elastic-test*\"],\n\t\"settings\":{\n\t\t\"number_of_shards\":1,\n\t\t\"number_of_replicas\":0\n\t},\n\t\"mappings\":{\n\t\t\"properties\":{\n\t\t\t\"tags\":{\n\t\t\t\t\"type\":\"keyword\"\n\t\t\t},\n\t\t\t\"location\":{\n\t\t\t\t\"type\":\"geo_point\"\n\t\t\t},\n\t\t\t\"suggest_field\":{\n\t\t\t\t\"type\":\"completion\"\n\t\t\t}\n\t\t}\n\t}\n}`\n\tputres, err := client.IndexPutTemplate(\"elastic-template\").BodyString(tmpl).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif putres == nil {\n\t\tt.Fatalf(\"expected response; got: %v\", putres)\n\t}\n\tif !putres.Acknowledged {\n\t\tt.Fatalf(\"expected index template to be ack'd; got: %v\", putres.Acknowledged)\n\t}\n\n\t// Always delete template\n\tdefer client.IndexDeleteTemplate(\"elastic-template\").Do(context.TODO())\n\n\t// Check if template exists\n\texists, err := client.IndexTemplateExists(\"elastic-template\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif !exists {\n\t\tt.Fatalf(\"expected index template %q to exist; got: %v\", \"elastic-template\", exists)\n\t}\n\n\t// Get template\n\tgetres, err := client.IndexGetTemplate(\"elastic-template\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif getres == nil {\n\t\tt.Fatalf(\"expected to get index template %q; got: %v\", \"elastic-template\", getres)\n\t}\n}\n"
  },
  {
    "path": "indices_exists_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesExistsWithoutIndex(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// No index name -> fail with error\n\tres, err := NewIndicesExistsService(client).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected IndicesExists to fail without index name\")\n\t}\n\tif res != false {\n\t\tt.Fatalf(\"expected result to be false; got: %v\", res)\n\t}\n}\n"
  },
  {
    "path": "indices_flush.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// Flush allows to flush one or more indices. The flush process of an index\n// basically frees memory from the index by flushing data to the index\n// storage and clearing the internal transaction log.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-flush.html\n// for details.\ntype IndicesFlushService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tforce             *bool\n\twaitIfOngoing     *bool\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n}\n\n// NewIndicesFlushService creates a new IndicesFlushService.\nfunc NewIndicesFlushService(client *Client) *IndicesFlushService {\n\treturn &IndicesFlushService{\n\t\tclient: client,\n\t\tindex:  make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesFlushService) Pretty(pretty bool) *IndicesFlushService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesFlushService) Human(human bool) *IndicesFlushService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesFlushService) ErrorTrace(errorTrace bool) *IndicesFlushService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesFlushService) FilterPath(filterPath ...string) *IndicesFlushService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesFlushService) Header(name string, value string) *IndicesFlushService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesFlushService) Headers(headers http.Header) *IndicesFlushService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names; use `_all` or empty string for all indices.\nfunc (s *IndicesFlushService) Index(indices ...string) *IndicesFlushService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// Force indicates whether a flush should be forced even if it is not\n// necessarily needed ie. if no changes will be committed to the index.\n// This is useful if transaction log IDs should be incremented even if\n// no uncommitted changes are present. (This setting can be considered as internal).\nfunc (s *IndicesFlushService) Force(force bool) *IndicesFlushService {\n\ts.force = &force\n\treturn s\n}\n\n// WaitIfOngoing, if set to true, indicates that the flush operation will\n// block until the flush can be executed if another flush operation is\n// already executing. The default is false and will cause an exception\n// to be thrown on the shard level if another flush operation is already running..\nfunc (s *IndicesFlushService) WaitIfOngoing(waitIfOngoing bool) *IndicesFlushService {\n\ts.waitIfOngoing = &waitIfOngoing\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesFlushService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesFlushService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices expression\n// resolves into no concrete indices. (This includes `_all` string or when\n// no indices have been specified).\nfunc (s *IndicesFlushService) AllowNoIndices(allowNoIndices bool) *IndicesFlushService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards specifies whether to expand wildcard expression to\n// concrete indices that are open, closed or both..\nfunc (s *IndicesFlushService) ExpandWildcards(expandWildcards string) *IndicesFlushService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesFlushService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_flush\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_flush\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.force != nil {\n\t\tparams.Set(\"force\", fmt.Sprintf(\"%v\", *s.force))\n\t}\n\tif s.waitIfOngoing != nil {\n\t\tparams.Set(\"wait_if_ongoing\", fmt.Sprintf(\"%v\", *s.waitIfOngoing))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesFlushService) Validate() error {\n\treturn nil\n}\n\n// Do executes the service.\nfunc (s *IndicesFlushService) Do(ctx context.Context) (*IndicesFlushResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesFlushResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a flush request.\n\ntype IndicesFlushResponse struct {\n\tShards *ShardsInfo `json:\"_shards\"`\n}\n"
  },
  {
    "path": "indices_flush_synced.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesSyncedFlushService performs a normal flush, then adds a generated\n// unique marked (sync_id) to all shards.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-synced-flush.html\n// for details.\ntype IndicesSyncedFlushService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n}\n\n// NewIndicesSyncedFlushService creates a new IndicesSyncedFlushService.\nfunc NewIndicesSyncedFlushService(client *Client) *IndicesSyncedFlushService {\n\treturn &IndicesSyncedFlushService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesSyncedFlushService) Pretty(pretty bool) *IndicesSyncedFlushService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesSyncedFlushService) Human(human bool) *IndicesSyncedFlushService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesSyncedFlushService) ErrorTrace(errorTrace bool) *IndicesSyncedFlushService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesSyncedFlushService) FilterPath(filterPath ...string) *IndicesSyncedFlushService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesSyncedFlushService) Header(name string, value string) *IndicesSyncedFlushService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesSyncedFlushService) Headers(headers http.Header) *IndicesSyncedFlushService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names; use `_all` or empty string for all indices.\nfunc (s *IndicesSyncedFlushService) Index(indices ...string) *IndicesSyncedFlushService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesSyncedFlushService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesSyncedFlushService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices expression\n// resolves into no concrete indices. (This includes `_all` string or when\n// no indices have been specified).\nfunc (s *IndicesSyncedFlushService) AllowNoIndices(allowNoIndices bool) *IndicesSyncedFlushService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards specifies whether to expand wildcard expression to\n// concrete indices that are open, closed or both..\nfunc (s *IndicesSyncedFlushService) ExpandWildcards(expandWildcards string) *IndicesSyncedFlushService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesSyncedFlushService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_flush/synced\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_flush/synced\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesSyncedFlushService) Validate() error {\n\treturn nil\n}\n\n// Do executes the service.\n//\n// Deprecated: Synced flush is deprecated and will be removed in 8.0.\n// Use flush at _/flush or /{index}/_flush instead.\nfunc (s *IndicesSyncedFlushService) Do(ctx context.Context) (*IndicesSyncedFlushResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesSyncedFlushResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a flush request.\n\n// IndicesSyncedFlushResponse is the outcome of a synched flush call.\ntype IndicesSyncedFlushResponse struct {\n\tShards *ShardsInfo                                `json:\"_shards\"`\n\tIndex  map[string]*IndicesShardsSyncedFlushResult `json:\"-\"`\n\n\t// TODO Add information about the indices here from the root level\n\t// It looks like this:\n\t// {\n\t// \t\"_shards\" : {\n\t// \t  \"total\" : 4,\n\t// \t  \"successful\" : 4,\n\t// \t  \"failed\" : 0\n\t// \t},\n\t// \t\"elastic-test\" : {\n\t// \t  \"total\" : 1,\n\t// \t  \"successful\" : 1,\n\t// \t  \"failed\" : 0\n\t// \t},\n\t// \t\"elastic-test2\" : {\n\t// \t  \"total\" : 1,\n\t// \t  \"successful\" : 1,\n\t// \t  \"failed\" : 0\n\t// \t},\n\t// \t\"elastic-orders\" : {\n\t// \t  \"total\" : 1,\n\t// \t  \"successful\" : 1,\n\t// \t  \"failed\" : 0\n\t// \t},\n\t// \t\"elastic-nosource-test\" : {\n\t// \t  \"total\" : 1,\n\t// \t  \"successful\" : 1,\n\t// \t  \"failed\" : 0\n\t// \t}\n\t// }\n}\n\n// IndicesShardsSyncedFlushResult represents synced flush information about\n// a specific index.\ntype IndicesShardsSyncedFlushResult struct {\n\tTotal      int                                     `json:\"total\"`\n\tSuccessful int                                     `json:\"successful\"`\n\tFailed     int                                     `json:\"failed\"`\n\tFailures   []IndicesShardsSyncedFlushResultFailure `json:\"failures,omitempty\"`\n}\n\n// IndicesShardsSyncedFlushResultFailure represents a failure of a synced\n// flush operation.\ntype IndicesShardsSyncedFlushResultFailure struct {\n\tShard   int    `json:\"shard\"`\n\tReason  string `json:\"reason\"`\n\tRouting struct {\n\t\tState                    string  `json:\"state\"`\n\t\tPrimary                  bool    `json:\"primary\"`\n\t\tNode                     string  `json:\"node\"`\n\t\tRelocatingNode           *string `json:\"relocating_node\"`\n\t\tShard                    int     `json:\"shard\"`\n\t\tIndex                    string  `json:\"index\"`\n\t\tExpectedShardSizeInBytes int64   `json:\"expected_shard_size_in_bytes,omitempty\"`\n\t\t// recoverySource\n\t\t// allocationId\n\t\t// unassignedInfo\n\t} `json:\"routing\"`\n}\n\n// UnmarshalJSON parses the output from Synced Flush API.\nfunc (resp *IndicesSyncedFlushResponse) UnmarshalJSON(data []byte) error {\n\tm := make(map[string]json.RawMessage)\n\terr := json.Unmarshal(data, &m)\n\tif err != nil {\n\t\treturn err\n\t}\n\tresp.Index = make(map[string]*IndicesShardsSyncedFlushResult)\n\tfor k, v := range m {\n\t\tif k == \"_shards\" {\n\t\t\tif err := json.Unmarshal(v, &resp.Shards); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t} else {\n\t\t\tix := new(IndicesShardsSyncedFlushResult)\n\t\t\tif err := json.Unmarshal(v, &ix); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tresp.Index[k] = ix\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "indices_flush_synced_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSyncedFlush(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\t//client := setupTestClientAndCreateIndexAndLog(t)\n\n\t// Sync Flush all indices\n\tres, err := client.SyncedFlush().Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Errorf(\"expected res to be != nil; got: %v\", res)\n\t}\n}\n\nfunc TestSyncedFlushBuildURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices               []string\n\t\tExpected              string\n\t\tExpectValidateFailure bool\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t\"/_flush/synced\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t\"/index1/_flush/synced\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t\"/index1%2Cindex2/_flush/synced\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\terr := NewIndicesSyncedFlushService(client).Index(test.Indices...).Validate()\n\t\tif err == nil && test.ExpectValidateFailure {\n\t\t\tt.Errorf(\"case #%d: expected validate to fail\", i+1)\n\t\t\tcontinue\n\t\t}\n\t\tif err != nil && !test.ExpectValidateFailure {\n\t\t\tt.Errorf(\"case #%d: expected validate to succeed\", i+1)\n\t\t\tcontinue\n\t\t}\n\t\tif !test.ExpectValidateFailure {\n\t\t\tpath, _, err := NewIndicesSyncedFlushService(client).Index(test.Indices...).buildURL()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"case #%d: %v\", i+1, err)\n\t\t\t}\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestSyncedFlushResponse(t *testing.T) {\n\tjs := `{\n\t\t\"_shards\": {\n\t\t   \"total\": 4,\n\t\t   \"successful\": 1,\n\t\t   \"failed\": 1\n\t\t},\n\t\t\"twitter\": {\n\t\t   \"total\": 4,\n\t\t   \"successful\": 3,\n\t\t   \"failed\": 1,\n\t\t   \"failures\": [\n\t\t\t  {\n\t\t\t\t \"shard\": 1,\n\t\t\t\t \"reason\": \"unexpected error\",\n\t\t\t\t \"routing\": {\n\t\t\t\t\t\"state\": \"STARTED\",\n\t\t\t\t\t\"primary\": false,\n\t\t\t\t\t\"node\": \"SZNr2J_ORxKTLUCydGX4zA\",\n\t\t\t\t\t\"relocating_node\": null,\n\t\t\t\t\t\"shard\": 1,\n\t\t\t\t\t\"index\": \"twitter\"\n\t\t\t\t }\n\t\t\t  }\n\t\t   ]\n\t\t}\n\t }`\n\n\tvar resp IndicesSyncedFlushResponse\n\tif err := json.Unmarshal([]byte(js), &resp); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := 4, resp.Shards.Total; want != have {\n\t\tt.Fatalf(\"want Shards.Total = %v, have %v\", want, have)\n\t}\n\tif want, have := 1, resp.Shards.Successful; want != have {\n\t\tt.Fatalf(\"want Shards.Successful = %v, have %v\", want, have)\n\t}\n\tif want, have := 1, resp.Shards.Failed; want != have {\n\t\tt.Fatalf(\"want Shards.Failed = %v, have %v\", want, have)\n\t}\n\n\t{\n\t\tindexName := \"twitter\"\n\t\tindex, found := resp.Index[indexName]\n\t\tif !found {\n\t\t\tt.Fatalf(\"want index %q\", indexName)\n\t\t}\n\t\tif index == nil {\n\t\t\tt.Fatalf(\"want index %q\", indexName)\n\t\t}\n\t\tif want, have := 4, index.Total; want != have {\n\t\t\tt.Fatalf(\"want Index[%q].Total = %v, have %v\", indexName, want, have)\n\t\t}\n\t\tif want, have := 3, index.Successful; want != have {\n\t\t\tt.Fatalf(\"want Index[%q].Successful = %v, have %v\", indexName, want, have)\n\t\t}\n\t\tif want, have := 1, index.Failed; want != have {\n\t\t\tt.Fatalf(\"want Index[%q].Failed = %v, have %v\", indexName, want, have)\n\t\t}\n\t\tif want, have := 1, len(index.Failures); want != have {\n\t\t\tt.Fatalf(\"want len(Index[%q].Failures) = %v, have %v\", indexName, want, have)\n\t\t}\n\t\tfailure := index.Failures[0]\n\t\tif want, have := 1, failure.Shard; want != have {\n\t\t\tt.Fatalf(\"want Index[%q].Failures[0].Shard = %v, have %v\", indexName, want, have)\n\t\t}\n\t\tif want, have := \"unexpected error\", failure.Reason; want != have {\n\t\t\tt.Fatalf(\"want Index[%q].Failures[0].Reason = %q, have %q\", indexName, want, have)\n\t\t}\n\t\tif want, have := false, failure.Routing.Primary; want != have {\n\t\t\tt.Fatalf(\"want Index[%q].Failures[0].Routing.Primary = %v, have %v\", indexName, want, have)\n\t\t}\n\t\tif want, have := \"SZNr2J_ORxKTLUCydGX4zA\", failure.Routing.Node; want != have {\n\t\t\tt.Fatalf(\"want Index[%q].Failures[0].Routing.Node = %q, have %q\", indexName, want, have)\n\t\t}\n\t\tif have := failure.Routing.RelocatingNode; have != nil {\n\t\t\tt.Fatalf(\"want Index[%q].Failures[0].Routing.RelocatingNode = nil, have %v\", indexName, have)\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "indices_flush_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestFlush(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// Flush all indices\n\tres, err := client.Flush().Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Errorf(\"expected res to be != nil; got: %v\", res)\n\t}\n}\n\nfunc TestFlushBuildURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices               []string\n\t\tExpected              string\n\t\tExpectValidateFailure bool\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t\"/_flush\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t\"/index1/_flush\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t\"/index1%2Cindex2/_flush\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\terr := NewIndicesFlushService(client).Index(test.Indices...).Validate()\n\t\tif err == nil && test.ExpectValidateFailure {\n\t\t\tt.Errorf(\"case #%d: expected validate to fail\", i+1)\n\t\t\tcontinue\n\t\t}\n\t\tif err != nil && !test.ExpectValidateFailure {\n\t\t\tt.Errorf(\"case #%d: expected validate to succeed\", i+1)\n\t\t\tcontinue\n\t\t}\n\t\tif !test.ExpectValidateFailure {\n\t\t\tpath, _, err := NewIndicesFlushService(client).Index(test.Indices...).buildURL()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"case #%d: %v\", i+1, err)\n\t\t\t}\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_forcemerge.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesForcemergeService allows to force merging of one or more indices.\n// The merge relates to the number of segments a Lucene index holds\n// within each shard. The force merge operation allows to reduce the number\n// of segments by merging them.\n//\n// See http://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-forcemerge.html\n// for more information.\ntype IndicesForcemergeService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex              []string\n\tallowNoIndices     *bool\n\texpandWildcards    string\n\tflush              *bool\n\tignoreUnavailable  *bool\n\tmaxNumSegments     interface{}\n\tonlyExpungeDeletes *bool\n}\n\n// NewIndicesForcemergeService creates a new IndicesForcemergeService.\nfunc NewIndicesForcemergeService(client *Client) *IndicesForcemergeService {\n\treturn &IndicesForcemergeService{\n\t\tclient: client,\n\t\tindex:  make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesForcemergeService) Pretty(pretty bool) *IndicesForcemergeService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesForcemergeService) Human(human bool) *IndicesForcemergeService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesForcemergeService) ErrorTrace(errorTrace bool) *IndicesForcemergeService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesForcemergeService) FilterPath(filterPath ...string) *IndicesForcemergeService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesForcemergeService) Header(name string, value string) *IndicesForcemergeService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesForcemergeService) Headers(headers http.Header) *IndicesForcemergeService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names; use `_all` or empty string to perform\n// the operation on all indices.\nfunc (s *IndicesForcemergeService) Index(index ...string) *IndicesForcemergeService {\n\tif s.index == nil {\n\t\ts.index = make([]string, 0)\n\t}\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices.\n// (This includes `_all` string or when no indices have been specified).\nfunc (s *IndicesForcemergeService) AllowNoIndices(allowNoIndices bool) *IndicesForcemergeService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both..\nfunc (s *IndicesForcemergeService) ExpandWildcards(expandWildcards string) *IndicesForcemergeService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// Flush specifies whether the index should be flushed after performing\n// the operation (default: true).\nfunc (s *IndicesForcemergeService) Flush(flush bool) *IndicesForcemergeService {\n\ts.flush = &flush\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should\n// be ignored when unavailable (missing or closed).\nfunc (s *IndicesForcemergeService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesForcemergeService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// MaxNumSegments specifies the number of segments the index should be\n// merged into (default: dynamic).\nfunc (s *IndicesForcemergeService) MaxNumSegments(maxNumSegments interface{}) *IndicesForcemergeService {\n\ts.maxNumSegments = maxNumSegments\n\treturn s\n}\n\n// OnlyExpungeDeletes specifies whether the operation should only expunge\n// deleted documents.\nfunc (s *IndicesForcemergeService) OnlyExpungeDeletes(onlyExpungeDeletes bool) *IndicesForcemergeService {\n\ts.onlyExpungeDeletes = &onlyExpungeDeletes\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesForcemergeService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\t// Build URL\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_forcemerge\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_forcemerge\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.flush != nil {\n\t\tparams.Set(\"flush\", fmt.Sprintf(\"%v\", *s.flush))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.maxNumSegments != nil {\n\t\tparams.Set(\"max_num_segments\", fmt.Sprintf(\"%v\", s.maxNumSegments))\n\t}\n\tif s.onlyExpungeDeletes != nil {\n\t\tparams.Set(\"only_expunge_deletes\", fmt.Sprintf(\"%v\", *s.onlyExpungeDeletes))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesForcemergeService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesForcemergeService) Do(ctx context.Context) (*IndicesForcemergeResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesForcemergeResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesForcemergeResponse is the response of IndicesForcemergeService.Do.\ntype IndicesForcemergeResponse struct {\n\tShards *ShardsInfo `json:\"_shards\"`\n}\n"
  },
  {
    "path": "indices_forcemerge_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesForcemergeBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t\"/_forcemerge\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t\"/index1/_forcemerge\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t\"/index1%2Cindex2/_forcemerge\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.Forcemerge().Index(test.Indices...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndicesForcemerge(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t_, err := client.Forcemerge(testIndexName).MaxNumSegments(1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t/*\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected forcemerge to succeed; got: %v\", ok)\n\t\t}\n\t*/\n}\n"
  },
  {
    "path": "indices_freeze.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesFreezeService freezes an index.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/freeze-index-api.html\n// and https://www.elastic.co/blog/creating-frozen-indices-with-the-elasticsearch-freeze-index-api\n// for details.\n//\n// Deprecated: Frozen indices are deprecated because they provide no benefit\n// given improvements in heap memory utilization.\ntype IndicesFreezeService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex               string\n\ttimeout             string\n\tmasterTimeout       string\n\tignoreUnavailable   *bool\n\tallowNoIndices      *bool\n\texpandWildcards     string\n\twaitForActiveShards string\n}\n\n// NewIndicesFreezeService creates a new IndicesFreezeService.\nfunc NewIndicesFreezeService(client *Client) *IndicesFreezeService {\n\treturn &IndicesFreezeService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesFreezeService) Pretty(pretty bool) *IndicesFreezeService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesFreezeService) Human(human bool) *IndicesFreezeService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesFreezeService) ErrorTrace(errorTrace bool) *IndicesFreezeService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesFreezeService) FilterPath(filterPath ...string) *IndicesFreezeService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesFreezeService) Header(name string, value string) *IndicesFreezeService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesFreezeService) Headers(headers http.Header) *IndicesFreezeService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the index to freeze.\nfunc (s *IndicesFreezeService) Index(index string) *IndicesFreezeService {\n\ts.index = index\n\treturn s\n}\n\n// Timeout allows to specify an explicit timeout.\nfunc (s *IndicesFreezeService) Timeout(timeout string) *IndicesFreezeService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout allows to specify a timeout for connection to master.\nfunc (s *IndicesFreezeService) MasterTimeout(masterTimeout string) *IndicesFreezeService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesFreezeService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesFreezeService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices expression\n// resolves into no concrete indices. (This includes `_all` string or when\n// no indices have been specified).\nfunc (s *IndicesFreezeService) AllowNoIndices(allowNoIndices bool) *IndicesFreezeService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards specifies whether to expand wildcard expression to\n// concrete indices that are open, closed or both..\nfunc (s *IndicesFreezeService) ExpandWildcards(expandWildcards string) *IndicesFreezeService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// WaitForActiveShards sets the number of active shards to wait for\n// before the operation returns.\nfunc (s *IndicesFreezeService) WaitForActiveShards(numShards string) *IndicesFreezeService {\n\ts.waitForActiveShards = numShards\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesFreezeService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/_freeze\", map[string]string{\n\t\t\"index\": s.index,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesFreezeService) Validate() error {\n\tvar invalid []string\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the service.\n//\n// Deprecated: Frozen indices are deprecated because they provide no benefit\n// given improvements in heap memory utilization.\nfunc (s *IndicesFreezeService) Do(ctx context.Context) (*IndicesFreezeResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesFreezeResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesFreezeResponse is the outcome of freezing an index.\ntype IndicesFreezeResponse struct {\n\tShards *ShardsInfo `json:\"_shards\"`\n}\n"
  },
  {
    "path": "indices_freeze_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestIndicesFreezeBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndex    string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"index1\",\n\t\t\t\"/index1/_freeze\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.FreezeIndex(test.Index).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_get.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesGetService retrieves information about one or more indices.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-get-index.html\n// for more details.\ntype IndicesGetService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tfeature           []string\n\tlocal             *bool\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n\tflatSettings      *bool\n}\n\n// NewIndicesGetService creates a new IndicesGetService.\nfunc NewIndicesGetService(client *Client) *IndicesGetService {\n\treturn &IndicesGetService{\n\t\tclient:  client,\n\t\tindex:   make([]string, 0),\n\t\tfeature: make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesGetService) Pretty(pretty bool) *IndicesGetService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesGetService) Human(human bool) *IndicesGetService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesGetService) ErrorTrace(errorTrace bool) *IndicesGetService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesGetService) FilterPath(filterPath ...string) *IndicesGetService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesGetService) Header(name string, value string) *IndicesGetService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesGetService) Headers(headers http.Header) *IndicesGetService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names.\nfunc (s *IndicesGetService) Index(indices ...string) *IndicesGetService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// Feature is a list of features.\nfunc (s *IndicesGetService) Feature(features ...string) *IndicesGetService {\n\ts.feature = append(s.feature, features...)\n\treturn s\n}\n\n// Local indicates whether to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *IndicesGetService) Local(local bool) *IndicesGetService {\n\ts.local = &local\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether to ignore unavailable indexes (default: false).\nfunc (s *IndicesGetService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesGetService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard expression\n// resolves to no concrete indices (default: false).\nfunc (s *IndicesGetService) AllowNoIndices(allowNoIndices bool) *IndicesGetService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether wildcard expressions should get\n// expanded to open or closed indices (default: open).\nfunc (s *IndicesGetService) ExpandWildcards(expandWildcards string) *IndicesGetService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesGetService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\tvar index []string\n\n\tif len(s.index) > 0 {\n\t\tindex = s.index\n\t} else {\n\t\tindex = []string{\"_all\"}\n\t}\n\n\tif len(s.feature) > 0 {\n\t\t// Build URL\n\t\tpath, err = uritemplates.Expand(\"/{index}/{feature}\", map[string]string{\n\t\t\t\"index\":   strings.Join(index, \",\"),\n\t\t\t\"feature\": strings.Join(s.feature, \",\"),\n\t\t})\n\t} else {\n\t\t// Build URL\n\t\tpath, err = uritemplates.Expand(\"/{index}\", map[string]string{\n\t\t\t\"index\": strings.Join(index, \",\"),\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprintf(\"%v\", *s.flatSettings))\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesGetService) Validate() error {\n\tvar invalid []string\n\tif len(s.index) == 0 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesGetService) Do(ctx context.Context) (map[string]*IndicesGetResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret map[string]*IndicesGetResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesGetResponse is part of the response of IndicesGetService.Do.\ntype IndicesGetResponse struct {\n\tAliases  map[string]interface{} `json:\"aliases\"`\n\tMappings map[string]interface{} `json:\"mappings\"`\n\tSettings map[string]interface{} `json:\"settings\"`\n\tWarmers  map[string]interface{} `json:\"warmers\"`\n}\n"
  },
  {
    "path": "indices_get_aliases.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// AliasesService returns the aliases associated with one or more indices, or the\n// indices associated with one or more aliases, or a combination of those filters.\n// See http://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-aliases.html.\ntype AliasesService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex []string\n\talias []string\n}\n\n// NewAliasesService instantiates a new AliasesService.\nfunc NewAliasesService(client *Client) *AliasesService {\n\tbuilder := &AliasesService{\n\t\tclient: client,\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *AliasesService) Pretty(pretty bool) *AliasesService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *AliasesService) Human(human bool) *AliasesService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *AliasesService) ErrorTrace(errorTrace bool) *AliasesService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *AliasesService) FilterPath(filterPath ...string) *AliasesService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *AliasesService) Header(name string, value string) *AliasesService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *AliasesService) Headers(headers http.Header) *AliasesService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index adds one or more indices.\nfunc (s *AliasesService) Index(index ...string) *AliasesService {\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// Alias adds one or more aliases.\nfunc (s *AliasesService) Alias(alias ...string) *AliasesService {\n\ts.alias = append(s.alias, alias...)\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *AliasesService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_alias/{alias}\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t\t\"alias\": strings.Join(s.alias, \",\"),\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/_alias/{alias}\", map[string]string{\n\t\t\t\"alias\": strings.Join(s.alias, \",\"),\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\tpath = strings.TrimSuffix(path, \"/\")\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\nfunc (s *AliasesService) Do(ctx context.Context) (*AliasesResult, error) {\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// {\n\t//   \"indexName\" : {\n\t//     \"aliases\" : {\n\t//       \"alias1\" : { },\n\t//       \"alias2\" : { }\n\t//     }\n\t//   },\n\t//   \"indexName2\" : {\n\t//     ...\n\t//   },\n\t// }\n\tindexMap := make(map[string]struct {\n\t\tAliases map[string]struct {\n\t\t\tIsWriteIndex bool `json:\"is_write_index\"`\n\t\t} `json:\"aliases\"`\n\t})\n\tif err := s.client.decoder.Decode(res.Body, &indexMap); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Each (indexName, _)\n\tret := &AliasesResult{\n\t\tIndices: make(map[string]indexResult),\n\t}\n\tfor indexName, indexData := range indexMap {\n\t\tif indexData.Aliases == nil {\n\t\t\tcontinue\n\t\t}\n\n\t\tindexOut, found := ret.Indices[indexName]\n\t\tif !found {\n\t\t\tindexOut = indexResult{Aliases: make([]aliasResult, 0)}\n\t\t}\n\n\t\t// { \"aliases\" : { ... } }\n\t\tfor aliasName, aliasData := range indexData.Aliases {\n\t\t\taliasRes := aliasResult{AliasName: aliasName, IsWriteIndex: aliasData.IsWriteIndex}\n\t\t\tindexOut.Aliases = append(indexOut.Aliases, aliasRes)\n\t\t}\n\n\t\tret.Indices[indexName] = indexOut\n\t}\n\n\treturn ret, nil\n}\n\n// -- Result of an alias request.\n\n// AliasesResult is the outcome of calling AliasesService.Do.\ntype AliasesResult struct {\n\tIndices map[string]indexResult\n}\n\ntype indexResult struct {\n\tAliases []aliasResult\n}\n\ntype aliasResult struct {\n\tAliasName    string\n\tIsWriteIndex bool\n}\n\n// IndicesByAlias returns all indices given a specific alias name.\nfunc (ar AliasesResult) IndicesByAlias(aliasName string) []string {\n\tvar indices []string\n\tfor indexName, indexInfo := range ar.Indices {\n\t\tfor _, aliasInfo := range indexInfo.Aliases {\n\t\t\tif aliasInfo.AliasName == aliasName {\n\t\t\t\tindices = append(indices, indexName)\n\t\t\t}\n\t\t}\n\t}\n\treturn indices\n}\n\n// HasAlias returns true if the index has a specific alias.\nfunc (ir indexResult) HasAlias(aliasName string) bool {\n\tfor _, alias := range ir.Aliases {\n\t\tif alias.AliasName == aliasName {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "indices_get_aliases_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestAliasesBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tAliases  []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"/_alias\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{},\n\t\t\t\"/index1/_alias\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{},\n\t\t\t\"/index1%2Cindex2/_alias\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{\"alias1\"},\n\t\t\t\"/index1%2Cindex2/_alias/alias1\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"alias1\"},\n\t\t\t\"/_alias/alias1\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{\"alias1\"},\n\t\t\t\"/index1/_alias/alias1\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{\"alias1\", \"alias2\"},\n\t\t\t\"/index1/_alias/alias1%2Calias2\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"alias1\", \"alias2\"},\n\t\t\t\"/_alias/alias1%2Calias2\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{\"alias1\", \"alias2\"},\n\t\t\t\"/index1%2Cindex2/_alias/alias1%2Calias2\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.Aliases().Index(test.Indices...).Alias(test.Aliases...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestAliases(t *testing.T) {\n\tvar err error\n\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// Some tweets\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\ttweet3 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\n\t// Add tweets to first index\n\t_, err = client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Add tweets to second index\n\t_, err = client.Index().Index(testIndexName2).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Refresh\n\t_, err = client.Refresh().Index(testIndexName, testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Alias should not yet exist\n\taliasesResult1, err := client.Aliases().\n\t\tIndex(testIndexName, testIndexName2).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(aliasesResult1.Indices) != 2 {\n\t\tt.Errorf(\"expected len(AliasesResult.Indices) = %d; got %d\", 2, len(aliasesResult1.Indices))\n\t}\n\tfor indexName, indexDetails := range aliasesResult1.Indices {\n\t\tif len(indexDetails.Aliases) != 0 {\n\t\t\tt.Errorf(\"expected len(AliasesResult.Indices[%s].Aliases) = %d; got %d\", indexName, 0, len(indexDetails.Aliases))\n\t\t}\n\t}\n\n\t// Add both indices to a new alias\n\taliasCreate, err := client.Alias().\n\t\tAdd(testIndexName, testAliasName).\n\t\tAction(\n\t\t\tNewAliasAddAction(testAliasName).\n\t\t\t\tIndex(testIndexName2).\n\t\t\t\tIsWriteIndex(true),\n\t\t).\n\t\t//Pretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !aliasCreate.Acknowledged {\n\t\tt.Errorf(\"expected AliasResult.Acknowledged %v; got %v\", true, aliasCreate.Acknowledged)\n\t}\n\n\t// Alias should now exist\n\taliasesResult2, err := client.Aliases().\n\t\tIndex(testIndexName, testIndexName2).\n\t\t//Pretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(aliasesResult2.Indices) != 2 {\n\t\tt.Errorf(\"expected len(AliasesResult.Indices) = %d; got %d\", 2, len(aliasesResult2.Indices))\n\t}\n\tfor indexName, indexDetails := range aliasesResult2.Indices {\n\t\tif len(indexDetails.Aliases) != 1 {\n\t\t\tt.Errorf(\"expected len(AliasesResult.Indices[%s].Aliases) = %d; got %d\", indexName, 1, len(indexDetails.Aliases))\n\t\t}\n\t}\n\tindicesResult, err := client.Aliases().\n\t\tAlias(testAliasName).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(indicesResult.Indices) != 2 {\n\t\tt.Errorf(\"expected len(indicesResult.Indices) = %d; got %d\", 2, len(indicesResult.Indices))\n\t}\n\tfor indexName, indexDetails := range indicesResult.Indices {\n\t\tif len(indexDetails.Aliases) != 1 {\n\t\t\tt.Errorf(\"expected len(indicesResult.Indices[%s].Aliases) = %d; got %d\", indexName, 1, len(indexDetails.Aliases))\n\t\t}\n\t\tif indexName == testIndexName2 {\n\t\t\tif !indexDetails.Aliases[0].IsWriteIndex {\n\t\t\t\tt.Errorf(\"expected alias on %s to be a write index\", testIndexName2)\n\t\t\t}\n\t\t}\n\t\tif indexName == testIndexName {\n\t\t\tif indexDetails.Aliases[0].IsWriteIndex {\n\t\t\t\tt.Errorf(\"expected alias on %s not to be a write index\", testIndexName2)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check the reverse function:\n\tindexInfo1, found := aliasesResult2.Indices[testIndexName]\n\tif !found {\n\t\tt.Errorf(\"expected info about index %s = %v; got %v\", testIndexName, true, found)\n\t}\n\taliasFound := indexInfo1.HasAlias(testAliasName)\n\tif !aliasFound {\n\t\tt.Errorf(\"expected alias %s to include index %s; got %v\", testAliasName, testIndexName, aliasFound)\n\t}\n\n\t// Check the reverse function:\n\tindexInfo2, found := aliasesResult2.Indices[testIndexName2]\n\tif !found {\n\t\tt.Errorf(\"expected info about index %s = %v; got %v\", testIndexName, true, found)\n\t}\n\taliasFound = indexInfo2.HasAlias(testAliasName)\n\tif !aliasFound {\n\t\tt.Errorf(\"expected alias %s to include index %s; got %v\", testAliasName, testIndexName2, aliasFound)\n\t}\n\n\t// Remove first index should remove two tweets, so should only yield 1\n\taliasRemove1, err := client.Alias().\n\t\tRemove(testIndexName, testAliasName).\n\t\t//Pretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !aliasRemove1.Acknowledged {\n\t\tt.Errorf(\"expected AliasResult.Acknowledged %v; got %v\", true, aliasRemove1.Acknowledged)\n\t}\n\n\t// Alias should now exist only for index 2\n\taliasesResult3, err := client.Aliases().Index(testIndexName, testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(aliasesResult3.Indices) != 2 {\n\t\tt.Errorf(\"expected len(AliasesResult.Indices) = %d; got %d\", 2, len(aliasesResult3.Indices))\n\t}\n\tfor indexName, indexDetails := range aliasesResult3.Indices {\n\t\tif indexName == testIndexName {\n\t\t\tif len(indexDetails.Aliases) != 0 {\n\t\t\t\tt.Errorf(\"expected len(AliasesResult.Indices[%s].Aliases) = %d; got %d\", indexName, 0, len(indexDetails.Aliases))\n\t\t\t}\n\t\t} else if indexName == testIndexName2 {\n\t\t\tif len(indexDetails.Aliases) != 1 {\n\t\t\t\tt.Errorf(\"expected len(AliasesResult.Indices[%s].Aliases) = %d; got %d\", indexName, 1, len(indexDetails.Aliases))\n\t\t\t}\n\t\t} else {\n\t\t\tt.Errorf(\"got index %s\", indexName)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_get_component_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesGetComponentTemplateService returns a component template.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.10/getting-component-templates.html\n// for more details.\ntype IndicesGetComponentTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname          []string\n\tmasterTimeout string\n\tflatSettings  *bool\n\tlocal         *bool\n}\n\n// NewIndicesGetComponentTemplateService creates a new IndicesGetComponentTemplateService.\nfunc NewIndicesGetComponentTemplateService(client *Client) *IndicesGetComponentTemplateService {\n\treturn &IndicesGetComponentTemplateService{\n\t\tclient: client,\n\t\tname:   make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesGetComponentTemplateService) Pretty(pretty bool) *IndicesGetComponentTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesGetComponentTemplateService) Human(human bool) *IndicesGetComponentTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesGetComponentTemplateService) ErrorTrace(errorTrace bool) *IndicesGetComponentTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesGetComponentTemplateService) FilterPath(filterPath ...string) *IndicesGetComponentTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesGetComponentTemplateService) Header(name string, value string) *IndicesGetComponentTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesGetComponentTemplateService) Headers(headers http.Header) *IndicesGetComponentTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the component template.\nfunc (s *IndicesGetComponentTemplateService) Name(name ...string) *IndicesGetComponentTemplateService {\n\ts.name = append(s.name, name...)\n\treturn s\n}\n\n// FlatSettings is returns settings in flat format (default: false).\nfunc (s *IndicesGetComponentTemplateService) FlatSettings(flatSettings bool) *IndicesGetComponentTemplateService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// Local indicates whether to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *IndicesGetComponentTemplateService) Local(local bool) *IndicesGetComponentTemplateService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesGetComponentTemplateService) MasterTimeout(masterTimeout string) *IndicesGetComponentTemplateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesGetComponentTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.name) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_component_template/{name}\", map[string]string{\n\t\t\t\"name\": strings.Join(s.name, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_component_template\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprintf(\"%v\", *s.flatSettings))\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesGetComponentTemplateService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesGetComponentTemplateService) Do(ctx context.Context) (*IndicesGetComponentTemplateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret *IndicesGetComponentTemplateResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesGetComponentTemplateResponse is the response of IndicesGetComponentTemplateService.Do.\ntype IndicesGetComponentTemplateResponse struct {\n\tComponentTemplates []IndicesGetComponentTemplates `json:\"component_templates\"`\n}\n\ntype IndicesGetComponentTemplates struct {\n\tName              string                       `json:\"name\"`\n\tComponentTemplate *IndicesGetComponentTemplate `json:\"component_template\"`\n}\n\ntype IndicesGetComponentTemplate struct {\n\tVersion  int                              `json:\"version,omitempty\"`\n\tTemplate *IndicesGetComponentTemplateData `json:\"template,omitempty\"`\n}\n\ntype IndicesGetComponentTemplateData struct {\n\tSettings map[string]interface{} `json:\"settings,omitempty\"`\n\tMappings map[string]interface{} `json:\"mappings,omitempty\"`\n\tAliases  map[string]interface{} `json:\"aliases,omitempty\"`\n}\n"
  },
  {
    "path": "indices_get_field_mapping.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesGetFieldMappingService retrieves the mapping definitions for the fields in an index\n//  or index/type.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-get-field-mapping.html\n// for details.\ntype IndicesGetFieldMappingService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\ttyp               []string\n\tfield             []string\n\tlocal             *bool\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n}\n\n// NewGetFieldMappingService is an alias for NewIndicesGetFieldMappingService.\n// Use NewIndicesGetFieldMappingService.\nfunc NewGetFieldMappingService(client *Client) *IndicesGetFieldMappingService {\n\treturn NewIndicesGetFieldMappingService(client)\n}\n\n// NewIndicesGetFieldMappingService creates a new IndicesGetFieldMappingService.\nfunc NewIndicesGetFieldMappingService(client *Client) *IndicesGetFieldMappingService {\n\treturn &IndicesGetFieldMappingService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesGetFieldMappingService) Pretty(pretty bool) *IndicesGetFieldMappingService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesGetFieldMappingService) Human(human bool) *IndicesGetFieldMappingService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesGetFieldMappingService) ErrorTrace(errorTrace bool) *IndicesGetFieldMappingService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesGetFieldMappingService) FilterPath(filterPath ...string) *IndicesGetFieldMappingService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesGetFieldMappingService) Header(name string, value string) *IndicesGetFieldMappingService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesGetFieldMappingService) Headers(headers http.Header) *IndicesGetFieldMappingService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names.\nfunc (s *IndicesGetFieldMappingService) Index(indices ...string) *IndicesGetFieldMappingService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// Type is a list of document types.\nfunc (s *IndicesGetFieldMappingService) Type(types ...string) *IndicesGetFieldMappingService {\n\ts.typ = append(s.typ, types...)\n\treturn s\n}\n\n// Field is a list of fields.\nfunc (s *IndicesGetFieldMappingService) Field(fields ...string) *IndicesGetFieldMappingService {\n\ts.field = append(s.field, fields...)\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices.\n// This includes `_all` string or when no indices have been specified.\nfunc (s *IndicesGetFieldMappingService) AllowNoIndices(allowNoIndices bool) *IndicesGetFieldMappingService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both..\nfunc (s *IndicesGetFieldMappingService) ExpandWildcards(expandWildcards string) *IndicesGetFieldMappingService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// Local indicates whether to return local information, do not retrieve\n// the state from master node (default: false).\nfunc (s *IndicesGetFieldMappingService) Local(local bool) *IndicesGetFieldMappingService {\n\ts.local = &local\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesGetFieldMappingService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesGetFieldMappingService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesGetFieldMappingService) buildURL() (string, url.Values, error) {\n\tvar index, typ, field []string\n\n\tif len(s.index) > 0 {\n\t\tindex = s.index\n\t} else {\n\t\tindex = []string{\"_all\"}\n\t}\n\n\tif len(s.typ) > 0 {\n\t\ttyp = s.typ\n\t} else {\n\t\ttyp = []string{\"_all\"}\n\t}\n\n\tif len(s.field) > 0 {\n\t\tfield = s.field\n\t} else {\n\t\tfield = []string{\"*\"}\n\t}\n\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/_mapping/{type}/field/{field}\", map[string]string{\n\t\t\"index\": strings.Join(index, \",\"),\n\t\t\"type\":  strings.Join(typ, \",\"),\n\t\t\"field\": strings.Join(field, \",\"),\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesGetFieldMappingService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation. It returns mapping definitions for an index\n// or index/type.\nfunc (s *IndicesGetFieldMappingService) Do(ctx context.Context) (map[string]interface{}, error) {\n\tvar ret map[string]interface{}\n\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n"
  },
  {
    "path": "indices_get_field_mapping_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestIndicesGetFieldMappingURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tTypes    []string\n\t\tFields   []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"/_all/_mapping/_all/field/%2A\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"tweet\"},\n\t\t\t[]string{\"message\"},\n\t\t\t\"/_all/_mapping/tweet/field/message\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"twitter\"},\n\t\t\t[]string{\"tweet\"},\n\t\t\t[]string{\"*.id\"},\n\t\t\t\"/twitter/_mapping/tweet/field/%2A.id\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"store-1\", \"store-2\"},\n\t\t\t[]string{\"tweet\", \"user\"},\n\t\t\t[]string{\"message\", \"*.id\"},\n\t\t\t\"/store-1%2Cstore-2/_mapping/tweet%2Cuser/field/message%2C%2A.id\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.GetFieldMapping().Index(test.Indices...).Type(test.Types...).Field(test.Fields...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_get_index_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesGetIndexTemplateService returns an index template.\n//\n// Index templates have changed during in 7.8 update of Elasticsearch.\n// This service implements the new version (7.8 or later). If you want\n// the old version, please use the IndicesGetTemplateService.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-get-template.html\n// for more details.\ntype IndicesGetIndexTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname          []string\n\tmasterTimeout string\n\tflatSettings  *bool\n\tlocal         *bool\n}\n\n// NewIndicesGetIndexTemplateService creates a new IndicesGetIndexTemplateService.\nfunc NewIndicesGetIndexTemplateService(client *Client) *IndicesGetIndexTemplateService {\n\treturn &IndicesGetIndexTemplateService{\n\t\tclient: client,\n\t\tname:   make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesGetIndexTemplateService) Pretty(pretty bool) *IndicesGetIndexTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesGetIndexTemplateService) Human(human bool) *IndicesGetIndexTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesGetIndexTemplateService) ErrorTrace(errorTrace bool) *IndicesGetIndexTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesGetIndexTemplateService) FilterPath(filterPath ...string) *IndicesGetIndexTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesGetIndexTemplateService) Header(name string, value string) *IndicesGetIndexTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesGetIndexTemplateService) Headers(headers http.Header) *IndicesGetIndexTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the index template.\nfunc (s *IndicesGetIndexTemplateService) Name(name ...string) *IndicesGetIndexTemplateService {\n\ts.name = append(s.name, name...)\n\treturn s\n}\n\n// FlatSettings is returns settings in flat format (default: false).\nfunc (s *IndicesGetIndexTemplateService) FlatSettings(flatSettings bool) *IndicesGetIndexTemplateService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// Local indicates whether to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *IndicesGetIndexTemplateService) Local(local bool) *IndicesGetIndexTemplateService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesGetIndexTemplateService) MasterTimeout(masterTimeout string) *IndicesGetIndexTemplateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesGetIndexTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.name) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_index_template/{name}\", map[string]string{\n\t\t\t\"name\": strings.Join(s.name, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_template\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprintf(\"%v\", *s.flatSettings))\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesGetIndexTemplateService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesGetIndexTemplateService) Do(ctx context.Context) (*IndicesGetIndexTemplateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret *IndicesGetIndexTemplateResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesGetIndexTemplateResponse is the response of IndicesGetIndexTemplateService.Do.\ntype IndicesGetIndexTemplateResponse struct {\n\tIndexTemplates IndicesGetIndexTemplatesSlice `json:\"index_templates\"`\n}\n\n// IndicesGetIndexTemplatesSlice is a slice of IndicesGetIndexTemplates.\ntype IndicesGetIndexTemplatesSlice []IndicesGetIndexTemplates\n\n// ByName returns the template with the given name, if it exists.\n// The bool indicates whether a template with that name has been found.\nfunc (slice IndicesGetIndexTemplatesSlice) ByName(name string) (*IndicesGetIndexTemplates, bool) {\n\tfor _, t := range slice {\n\t\tif t.Name == name {\n\t\t\treturn &t, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\ntype IndicesGetIndexTemplates struct {\n\tName          string                   `json:\"name\"`\n\tIndexTemplate *IndicesGetIndexTemplate `json:\"index_template\"`\n}\n\ntype IndicesGetIndexTemplate struct {\n\tIndexPatterns   []string                     `json:\"index_patterns,omitempty\"`\n\tComposedOf      []string                     `json:\"composed_of,omitempty\"`\n\tPriority        int                          `json:\"priority,omitempty\"`\n\tVersion         int                          `json:\"version,omitempty\"`\n\tTemplate        *IndicesGetIndexTemplateData `json:\"template,omitempty\"`\n\tMeta            map[string]interface{}       `json:\"_meta,omitempty\"`\n\tDataStream      *IndicesDataStream           `json:\"data_stream,omitempty\"`\n\tAllowAutoCreate bool                         `json:\"allow_auto_create,omitempty\"`\n}\n\ntype IndicesGetIndexTemplateData struct {\n\tSettings map[string]interface{} `json:\"settings,omitempty\"`\n\tMappings map[string]interface{} `json:\"mappings,omitempty\"`\n\tAliases  map[string]interface{} `json:\"aliases,omitempty\"`\n}\n\ntype IndicesDataStream struct {\n\tName               string                           `json:\"name,omitempty\"`\n\tTimestampField     *IndicesDataStreamTimestampField `json:\"timestamp_field,omitempty\"`\n\tIndices            []string                         `json:\"indices,omitempty\"`\n\tGeneration         int64                            `json:\"generation,omitempty\"`\n\tStatus             string                           `json:\"status,omitempty\"`\n\tIndexTemplate      string                           `json:\"template,omitempty\"`\n\tIlmPolicy          string                           `json:\"ilm_policy,omitempty\"`\n\tMeta               map[string]interface{}           `json:\"_meta,omitempty\"`\n\tHidden             bool                             `json:\"hidden,omitempty\"`\n\tSystem             bool                             `json:\"system,omitempty\"`\n\tAllowCustomRouting bool                             `json:\"allow_custom_routing,omitempty\"`\n\tReplicated         bool                             `json:\"replicated,omitempty\"`\n}\n\ntype IndicesDataStreamTimestampField struct {\n\tName string `json:\"name,omitempty\"`\n}\n"
  },
  {
    "path": "indices_get_index_template_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndexGetIndexTemplateURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tName     string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"template_1\",\n\t\t\t\"/_index_template/template_1\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.IndexGetIndexTemplate(test.Name).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndexGetIndexTemplateService(t *testing.T) {\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tcreate := true\n\tbody := `\n{\n\t\"index_patterns\": [\"te*\"],\n\t\"priority\": 1,\n\t\"template\": {\n\t\t\"settings\": {\n\t\t\t\"index\": {\n\t\t  \t\t\"number_of_shards\": 1\n\t\t\t}\n\t  \t},\n\t  \t\"mappings\": {\n\t\t\t\"_source\": {\n\t\t  \t\t\"enabled\": false\n\t\t\t},\n\t\t\t\"properties\": {\n\t\t  \t\t\"host_name\": {\n\t\t\t\t\t\"type\": \"keyword\"\n\t\t  \t\t},\n\t\t  \t\t\"created_at\": {\n\t\t\t\t\t\"type\": \"date\",\n\t\t\t\t\t\"format\": \"yyyy MM dd HH:mm:ss Z\"\n\t\t  \t\t}\n\t\t\t}\n\t  \t}\n  \t}\n}\n`\n\t_, err := client.IndexPutIndexTemplate(\"template_1\").BodyString(body).Create(create).Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer client.IndexDeleteIndexTemplate(\"template_1\").Pretty(true).Do(context.TODO())\n\n\tres, err := client.IndexGetIndexTemplate(\"template_1\").Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected result; got: %v\", res)\n\t}\n\ttemplate, found := res.IndexTemplates.ByName(\"template_1\")\n\tif !found {\n\t\tt.Fatalf(\"expected template %q to be found; got: %v\", \"template_1\", found)\n\t}\n\tif template == nil {\n\t\tt.Fatalf(\"expected template %q to be != nil; got: %v\", \"template_1\", template)\n\t}\n\tif template.IndexTemplate == nil {\n\t\tt.Fatalf(\"expected index template of template %q to be != nil; got: %v\", \"template_1\", template.IndexTemplate)\n\t}\n\tif len(template.IndexTemplate.IndexPatterns) != 1 || template.IndexTemplate.IndexPatterns[0] != \"te*\" {\n\t\tt.Fatalf(\"expected index settings of %q to be [\\\"index1\\\"]; got: %v\", testIndexName, template.IndexTemplate.IndexPatterns)\n\t}\n}\n"
  },
  {
    "path": "indices_get_mapping.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesGetMappingService retrieves the mapping definitions for an index or\n// index/type.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-get-mapping.html\n// for details.\ntype IndicesGetMappingService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\ttyp               []string\n\tlocal             *bool\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n}\n\n// NewGetMappingService is an alias for NewIndicesGetMappingService.\n// Use NewIndicesGetMappingService.\nfunc NewGetMappingService(client *Client) *IndicesGetMappingService {\n\treturn NewIndicesGetMappingService(client)\n}\n\n// NewIndicesGetMappingService creates a new IndicesGetMappingService.\nfunc NewIndicesGetMappingService(client *Client) *IndicesGetMappingService {\n\treturn &IndicesGetMappingService{\n\t\tclient: client,\n\t\tindex:  make([]string, 0),\n\t\ttyp:    make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesGetMappingService) Pretty(pretty bool) *IndicesGetMappingService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesGetMappingService) Human(human bool) *IndicesGetMappingService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesGetMappingService) ErrorTrace(errorTrace bool) *IndicesGetMappingService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesGetMappingService) FilterPath(filterPath ...string) *IndicesGetMappingService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesGetMappingService) Header(name string, value string) *IndicesGetMappingService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesGetMappingService) Headers(headers http.Header) *IndicesGetMappingService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names.\nfunc (s *IndicesGetMappingService) Index(indices ...string) *IndicesGetMappingService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// Type is a list of document types.\nfunc (s *IndicesGetMappingService) Type(types ...string) *IndicesGetMappingService {\n\ts.typ = append(s.typ, types...)\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices.\n// This includes `_all` string or when no indices have been specified.\nfunc (s *IndicesGetMappingService) AllowNoIndices(allowNoIndices bool) *IndicesGetMappingService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both..\nfunc (s *IndicesGetMappingService) ExpandWildcards(expandWildcards string) *IndicesGetMappingService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// Local indicates whether to return local information, do not retrieve\n// the state from master node (default: false).\nfunc (s *IndicesGetMappingService) Local(local bool) *IndicesGetMappingService {\n\ts.local = &local\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesGetMappingService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesGetMappingService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesGetMappingService) buildURL() (string, url.Values, error) {\n\tvar index, typ []string\n\n\tif len(s.index) > 0 {\n\t\tindex = s.index\n\t} else {\n\t\tindex = []string{\"_all\"}\n\t}\n\n\tif len(s.typ) > 0 {\n\t\ttyp = s.typ\n\t} else {\n\t\ttyp = []string{\"_all\"}\n\t}\n\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/_mapping/{type}\", map[string]string{\n\t\t\"index\": strings.Join(index, \",\"),\n\t\t\"type\":  strings.Join(typ, \",\"),\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesGetMappingService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation. It returns mapping definitions for an index\n// or index/type.\nfunc (s *IndicesGetMappingService) Do(ctx context.Context) (map[string]interface{}, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret map[string]interface{}\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n"
  },
  {
    "path": "indices_get_mapping_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestIndicesGetMappingURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tTypes    []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"/_all/_mapping/_all\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"tweet\"},\n\t\t\t\"/_all/_mapping/tweet\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"twitter\"},\n\t\t\t[]string{\"tweet\"},\n\t\t\t\"/twitter/_mapping/tweet\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"store-1\", \"store-2\"},\n\t\t\t[]string{\"tweet\", \"user\"},\n\t\t\t\"/store-1%2Cstore-2/_mapping/tweet%2Cuser\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.GetMapping().Index(test.Indices...).Type(test.Types...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_get_settings.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesGetSettingsService allows to retrieve settings of one\n// or more indices.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-get-settings.html\n// for more details.\ntype IndicesGetSettingsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tname              []string\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n\tflatSettings      *bool\n\tlocal             *bool\n}\n\n// NewIndicesGetSettingsService creates a new IndicesGetSettingsService.\nfunc NewIndicesGetSettingsService(client *Client) *IndicesGetSettingsService {\n\treturn &IndicesGetSettingsService{\n\t\tclient: client,\n\t\tindex:  make([]string, 0),\n\t\tname:   make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesGetSettingsService) Pretty(pretty bool) *IndicesGetSettingsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesGetSettingsService) Human(human bool) *IndicesGetSettingsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesGetSettingsService) ErrorTrace(errorTrace bool) *IndicesGetSettingsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesGetSettingsService) FilterPath(filterPath ...string) *IndicesGetSettingsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesGetSettingsService) Header(name string, value string) *IndicesGetSettingsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesGetSettingsService) Headers(headers http.Header) *IndicesGetSettingsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names; use `_all` or empty string to perform\n// the operation on all indices.\nfunc (s *IndicesGetSettingsService) Index(indices ...string) *IndicesGetSettingsService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// Name are the names of the settings that should be included.\nfunc (s *IndicesGetSettingsService) Name(name ...string) *IndicesGetSettingsService {\n\ts.name = append(s.name, name...)\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should\n// be ignored when unavailable (missing or closed).\nfunc (s *IndicesGetSettingsService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesGetSettingsService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices.\n// (This includes `_all` string or when no indices have been specified).\nfunc (s *IndicesGetSettingsService) AllowNoIndices(allowNoIndices bool) *IndicesGetSettingsService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression\n// to concrete indices that are open, closed or both.\n// Options: open, closed, none, all. Default: open,closed.\nfunc (s *IndicesGetSettingsService) ExpandWildcards(expandWildcards string) *IndicesGetSettingsService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// FlatSettings indicates whether to return settings in flat format (default: false).\nfunc (s *IndicesGetSettingsService) FlatSettings(flatSettings bool) *IndicesGetSettingsService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// Local indicates whether to return local information, do not retrieve\n// the state from master node (default: false).\nfunc (s *IndicesGetSettingsService) Local(local bool) *IndicesGetSettingsService {\n\ts.local = &local\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesGetSettingsService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\tvar index []string\n\n\tif len(s.index) > 0 {\n\t\tindex = s.index\n\t} else {\n\t\tindex = []string{\"_all\"}\n\t}\n\n\tif len(s.name) > 0 {\n\t\t// Build URL\n\t\tpath, err = uritemplates.Expand(\"/{index}/_settings/{name}\", map[string]string{\n\t\t\t\"index\": strings.Join(index, \",\"),\n\t\t\t\"name\":  strings.Join(s.name, \",\"),\n\t\t})\n\t} else {\n\t\t// Build URL\n\t\tpath, err = uritemplates.Expand(\"/{index}/_settings\", map[string]string{\n\t\t\t\"index\": strings.Join(index, \",\"),\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprintf(\"%v\", *s.flatSettings))\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesGetSettingsService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesGetSettingsService) Do(ctx context.Context) (map[string]*IndicesGetSettingsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret map[string]*IndicesGetSettingsResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesGetSettingsResponse is the response of IndicesGetSettingsService.Do.\ntype IndicesGetSettingsResponse struct {\n\tSettings map[string]interface{} `json:\"settings\"`\n}\n"
  },
  {
    "path": "indices_get_settings_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndexGetSettingsURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tNames    []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"/_all/_settings\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"index.merge.*\"},\n\t\t\t\"/_all/_settings/index.merge.%2A\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"twitter-*\"},\n\t\t\t[]string{\"index.merge.*\", \"_settings\"},\n\t\t\t\"/twitter-%2A/_settings/index.merge.%2A%2C_settings\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"store-1\", \"store-2\"},\n\t\t\t[]string{\"index.merge.*\", \"_settings\"},\n\t\t\t\"/store-1%2Cstore-2/_settings/index.merge.%2A%2C_settings\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.IndexGetSettings().Index(test.Indices...).Name(test.Names...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndexGetSettingsService(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tesversion, err := client.ElasticsearchVersion(DefaultURL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif esversion < \"1.4.0\" {\n\t\tt.Skip(\"Index Get API is available since 1.4\")\n\t\treturn\n\t}\n\n\tres, err := client.IndexGetSettings().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected result; got: %v\", res)\n\t}\n\tinfo, found := res[testIndexName]\n\tif !found {\n\t\tt.Fatalf(\"expected index %q to be found; got: %v\", testIndexName, found)\n\t}\n\tif info == nil {\n\t\tt.Fatalf(\"expected index %q to be != nil; got: %v\", testIndexName, info)\n\t}\n\tif info.Settings == nil {\n\t\tt.Fatalf(\"expected index settings of %q to be != nil; got: %v\", testIndexName, info.Settings)\n\t}\n}\n"
  },
  {
    "path": "indices_get_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesGetTemplateService returns an index template (v1).\n//\n// Index templates have changed during in 7.8 update of Elasticsearch.\n// This service implements the legacy version (7.7 or lower). If you want\n// the new version, please use the IndicesGetIndexTemplateService.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-get-template-v1.html\n// for more details.\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\ntype IndicesGetTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname         []string\n\tflatSettings *bool\n\tlocal        *bool\n}\n\n// NewIndicesGetTemplateService creates a new IndicesGetTemplateService.\nfunc NewIndicesGetTemplateService(client *Client) *IndicesGetTemplateService {\n\treturn &IndicesGetTemplateService{\n\t\tclient: client,\n\t\tname:   make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesGetTemplateService) Pretty(pretty bool) *IndicesGetTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesGetTemplateService) Human(human bool) *IndicesGetTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesGetTemplateService) ErrorTrace(errorTrace bool) *IndicesGetTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesGetTemplateService) FilterPath(filterPath ...string) *IndicesGetTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesGetTemplateService) Header(name string, value string) *IndicesGetTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesGetTemplateService) Headers(headers http.Header) *IndicesGetTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the index template.\nfunc (s *IndicesGetTemplateService) Name(name ...string) *IndicesGetTemplateService {\n\ts.name = append(s.name, name...)\n\treturn s\n}\n\n// FlatSettings is returns settings in flat format (default: false).\nfunc (s *IndicesGetTemplateService) FlatSettings(flatSettings bool) *IndicesGetTemplateService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// Local indicates whether to return local information, i.e. do not retrieve\n// the state from master node (default: false).\nfunc (s *IndicesGetTemplateService) Local(local bool) *IndicesGetTemplateService {\n\ts.local = &local\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesGetTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.name) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_template/{name}\", map[string]string{\n\t\t\t\"name\": strings.Join(s.name, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_template\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprintf(\"%v\", *s.flatSettings))\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesGetTemplateService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\nfunc (s *IndicesGetTemplateService) Do(ctx context.Context) (map[string]*IndicesGetTemplateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret map[string]*IndicesGetTemplateResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesGetTemplateResponse is the response of IndicesGetTemplateService.Do.\ntype IndicesGetTemplateResponse struct {\n\tOrder         int                    `json:\"order,omitempty\"`\n\tVersion       int                    `json:\"version,omitempty\"`\n\tIndexPatterns []string               `json:\"index_patterns,omitempty\"`\n\tSettings      map[string]interface{} `json:\"settings,omitempty\"`\n\tMappings      map[string]interface{} `json:\"mappings,omitempty\"`\n\tAliases       map[string]interface{} `json:\"aliases,omitempty\"`\n}\n"
  },
  {
    "path": "indices_get_template_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndexGetTemplateURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tNames    []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t\"/_template\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t\"/_template/index1\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t\"/_template/index1%2Cindex2\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.IndexGetTemplate().Name(test.Names...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndexGetTemplateService(t *testing.T) {\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tcreate := true\n\tbody := `\n{\n  \"index_patterns\": [\"te*\"],\n  \"settings\": {\n    \"index\": {\n      \"number_of_shards\": 1\n    }\n  },\n  \"mappings\": {\n    \"_source\": {\n      \"enabled\": false\n    },\n    \"properties\": {\n      \"host_name\": {\n        \"type\": \"keyword\"\n      },\n      \"created_at\": {\n        \"type\": \"date\",\n        \"format\": \"yyyy MM dd HH:mm:ss Z\"\n      }\n    }\n  }\n}\n`\n\t_, err := client.IndexPutTemplate(\"template_1\").BodyString(body).Create(create).Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer client.IndexDeleteTemplate(\"template_1\").Pretty(true).Do(context.TODO())\n\n\tres, err := client.IndexGetTemplate(\"template_1\").Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected result; got: %v\", res)\n\t}\n\ttemplate := res[\"template_1\"]\n\tif template == nil {\n\t\tt.Fatalf(\"expected template %q to be != nil; got: %v\", \"template_1\", template)\n\t}\n\tif len(template.IndexPatterns) != 1 || template.IndexPatterns[0] != \"te*\" {\n\t\tt.Fatalf(\"expected index settings of %q to be [\\\"index1\\\"]; got: %v\", testIndexName, template.IndexPatterns)\n\t}\n}\n"
  },
  {
    "path": "indices_get_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesGetValidate(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// No index name -> fail with error\n\tres, err := NewIndicesGetService(client).Index(\"\").Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected IndicesGet to fail without index name\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected result to be == nil; got: %v\", res)\n\t}\n}\n\nfunc TestIndicesGetURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tFeatures []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"/_all\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"_mappings\"},\n\t\t\t\"/_all/_mappings\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"twitter\"},\n\t\t\t[]string{\"_mappings\", \"_settings\"},\n\t\t\t\"/twitter/_mappings%2C_settings\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"store-1\", \"store-2\"},\n\t\t\t[]string{\"_mappings\", \"_settings\"},\n\t\t\t\"/store-1%2Cstore-2/_mappings%2C_settings\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := NewIndicesGetService(client).Index(test.Indices...).Feature(test.Features...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndicesGetService(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tesversion, err := client.ElasticsearchVersion(DefaultURL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif esversion < \"1.4.0\" {\n\t\tt.Skip(\"Index Get API is available since 1.4\")\n\t\treturn\n\t}\n\n\tres, err := client.IndexGet().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected result; got: %v\", res)\n\t}\n\tinfo, found := res[testIndexName]\n\tif !found {\n\t\tt.Fatalf(\"expected index %q to be found; got: %v\", testIndexName, found)\n\t}\n\tif info == nil {\n\t\tt.Fatalf(\"expected index %q to be != nil; got: %v\", testIndexName, info)\n\t}\n\tif info.Mappings == nil {\n\t\tt.Errorf(\"expected mappings to be != nil; got: %v\", info.Mappings)\n\t}\n\tif info.Settings == nil {\n\t\tt.Errorf(\"expected settings to be != nil; got: %v\", info.Settings)\n\t}\n}\n"
  },
  {
    "path": "indices_index_templates_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndexTemplatesLifecycle(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tconst templateName = \"template_1\"\n\n\t// Always make sure the index template is deleted\n\tdefer func() {\n\t\t_, _ = client.IndexDeleteIndexTemplate(templateName).Pretty(true).Do(context.Background())\n\t}()\n\n\t// Create an index template\n\t{\n\t\tresp, err := client.IndexPutIndexTemplate(templateName).Pretty(true).BodyString(`{\n\t\t\t\"index_patterns\": [\"elastic-index-templates-*\"],\n\t\t\t\"priority\": 1,\n\t\t\t\"template\": {\n\t\t\t\t\"settings\": {\n\t\t\t\t\t\"number_of_shards\": 2,\n\t\t\t\t\t\"number_of_replicas\": 0\n\t\t\t\t},\n\t\t\t\t\"mappings\": {\n\t\t\t\t\t\"_source\": { \"enabled\": true }\n\t\t\t\t}\n\t\t\t}\n\t\t}`).Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected to successfully create index template, got %v\", err)\n\t\t}\n\t\tif resp == nil {\n\t\t\tt.Fatal(\"expected response on creating index template\")\n\t\t}\n\t\tif want, have := true, resp.Acknowledged; want != have {\n\t\t\tt.Errorf(\"expected Acknowledged=%v, got %v\", want, have)\n\t\t}\n\t}\n\n\t// Get the index template\n\t{\n\t\tresp, err := client.IndexGetIndexTemplate(templateName).Pretty(true).Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected to successfully get index template, got %v\", err)\n\t\t}\n\t\tif resp == nil {\n\t\t\tt.Fatal(\"expected response on getting index template\")\n\t\t}\n\t}\n\n\t// Delete the index template\n\t{\n\t\tresp, err := client.IndexDeleteIndexTemplate(templateName).Pretty(true).Do(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"expected to successfully delete index template, got %v\", err)\n\t\t}\n\t\tif resp == nil {\n\t\t\tt.Fatal(\"expected response on deleting index template\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_open.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesOpenService opens an index.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-open-close.html\n// for details.\ntype IndicesOpenService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex               string\n\ttimeout             string\n\tmasterTimeout       string\n\tignoreUnavailable   *bool\n\tallowNoIndices      *bool\n\texpandWildcards     string\n\twaitForActiveShards string\n}\n\n// NewIndicesOpenService creates and initializes a new IndicesOpenService.\nfunc NewIndicesOpenService(client *Client) *IndicesOpenService {\n\treturn &IndicesOpenService{client: client}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesOpenService) Pretty(pretty bool) *IndicesOpenService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesOpenService) Human(human bool) *IndicesOpenService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesOpenService) ErrorTrace(errorTrace bool) *IndicesOpenService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesOpenService) FilterPath(filterPath ...string) *IndicesOpenService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesOpenService) Header(name string, value string) *IndicesOpenService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesOpenService) Headers(headers http.Header) *IndicesOpenService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the index to open.\nfunc (s *IndicesOpenService) Index(index string) *IndicesOpenService {\n\ts.index = index\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndicesOpenService) Timeout(timeout string) *IndicesOpenService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesOpenService) MasterTimeout(masterTimeout string) *IndicesOpenService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should\n// be ignored when unavailable (missing or closed).\nfunc (s *IndicesOpenService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesOpenService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices.\n// (This includes `_all` string or when no indices have been specified).\nfunc (s *IndicesOpenService) AllowNoIndices(allowNoIndices bool) *IndicesOpenService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both..\nfunc (s *IndicesOpenService) ExpandWildcards(expandWildcards string) *IndicesOpenService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// WaitForActiveShards specifies the number of shards that must be allocated\n// before the Open operation returns. Valid values are \"all\" or an integer\n// between 0 and number_of_replicas+1 (default: 0)\nfunc (s *IndicesOpenService) WaitForActiveShards(waitForActiveShards string) *IndicesOpenService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesOpenService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/_open\", map[string]string{\n\t\t\"index\": s.index,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesOpenService) Validate() error {\n\tvar invalid []string\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesOpenService) Do(ctx context.Context) (*IndicesOpenResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesOpenResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesOpenResponse is the response of IndicesOpenService.Do.\ntype IndicesOpenResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_open_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesOpenValidate(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// No index name -> fail with error\n\tres, err := NewIndicesOpenService(client).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected IndicesOpen to fail without index name\")\n\t}\n\tif res != nil {\n\t\tt.Fatalf(\"expected result to be == nil; got: %v\", res)\n\t}\n}\n"
  },
  {
    "path": "indices_put_alias.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// -- Actions --\n\n// AliasAction is an action to apply to an alias, e.g. \"add\" or \"remove\".\ntype AliasAction interface {\n\tSource() (interface{}, error)\n}\n\n// AliasAddAction is an action to add to an alias.\ntype AliasAddAction struct {\n\tindex         []string // index name(s)\n\talias         string   // alias name\n\tfilter        Query\n\trouting       string\n\tsearchRouting string\n\tindexRouting  string\n\tisWriteIndex  *bool\n}\n\n// NewAliasAddAction returns an action to add an alias.\nfunc NewAliasAddAction(alias string) *AliasAddAction {\n\treturn &AliasAddAction{\n\t\talias: alias,\n\t}\n}\n\n// Index associates one or more indices to the alias.\nfunc (a *AliasAddAction) Index(index ...string) *AliasAddAction {\n\ta.index = append(a.index, index...)\n\treturn a\n}\n\nfunc (a *AliasAddAction) removeBlankIndexNames() {\n\tvar indices []string\n\tfor _, index := range a.index {\n\t\tif len(index) > 0 {\n\t\t\tindices = append(indices, index)\n\t\t}\n\t}\n\ta.index = indices\n}\n\n// Filter associates a filter to the alias.\nfunc (a *AliasAddAction) Filter(filter Query) *AliasAddAction {\n\ta.filter = filter\n\treturn a\n}\n\n// Routing associates a routing value to the alias.\n// This basically sets index and search routing to the same value.\nfunc (a *AliasAddAction) Routing(routing string) *AliasAddAction {\n\ta.routing = routing\n\treturn a\n}\n\n// IndexRouting associates an index routing value to the alias.\nfunc (a *AliasAddAction) IndexRouting(routing string) *AliasAddAction {\n\ta.indexRouting = routing\n\treturn a\n}\n\n// SearchRouting associates a search routing value to the alias.\nfunc (a *AliasAddAction) SearchRouting(routing ...string) *AliasAddAction {\n\ta.searchRouting = strings.Join(routing, \",\")\n\treturn a\n}\n\n// IsWriteIndex associates an is_write_index flag to the alias.\nfunc (a *AliasAddAction) IsWriteIndex(flag bool) *AliasAddAction {\n\ta.isWriteIndex = &flag\n\treturn a\n}\n\n// Validate checks if the operation is valid.\nfunc (a *AliasAddAction) Validate() error {\n\tvar invalid []string\n\tif len(a.alias) == 0 {\n\t\tinvalid = append(invalid, \"Alias\")\n\t}\n\tif len(a.index) == 0 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\tif a.isWriteIndex != nil && len(a.index) > 1 {\n\t\treturn fmt.Errorf(\"more than 1 target index specified in operation with 'is_write_index' flag present\")\n\t}\n\treturn nil\n}\n\n// Source returns the JSON-serializable data.\nfunc (a *AliasAddAction) Source() (interface{}, error) {\n\ta.removeBlankIndexNames()\n\tif err := a.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\tsrc := make(map[string]interface{})\n\tact := make(map[string]interface{})\n\tsrc[\"add\"] = act\n\tact[\"alias\"] = a.alias\n\tswitch len(a.index) {\n\tcase 1:\n\t\tact[\"index\"] = a.index[0]\n\tdefault:\n\t\tact[\"indices\"] = a.index\n\t}\n\tif a.filter != nil {\n\t\tf, err := a.filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tact[\"filter\"] = f\n\t}\n\tif len(a.routing) > 0 {\n\t\tact[\"routing\"] = a.routing\n\t}\n\tif len(a.indexRouting) > 0 {\n\t\tact[\"index_routing\"] = a.indexRouting\n\t}\n\tif len(a.searchRouting) > 0 {\n\t\tact[\"search_routing\"] = a.searchRouting\n\t}\n\tif a.isWriteIndex != nil {\n\t\tact[\"is_write_index\"] = *a.isWriteIndex\n\t}\n\treturn src, nil\n}\n\n// AliasRemoveAction is an action to remove an alias.\ntype AliasRemoveAction struct {\n\tindex []string // index name(s)\n\talias string   // alias name\n}\n\n// NewAliasRemoveAction returns an action to remove an alias.\nfunc NewAliasRemoveAction(alias string) *AliasRemoveAction {\n\treturn &AliasRemoveAction{\n\t\talias: alias,\n\t}\n}\n\n// Index associates one or more indices to the alias.\nfunc (a *AliasRemoveAction) Index(index ...string) *AliasRemoveAction {\n\ta.index = append(a.index, index...)\n\treturn a\n}\n\nfunc (a *AliasRemoveAction) removeBlankIndexNames() {\n\tvar indices []string\n\tfor _, index := range a.index {\n\t\tif len(index) > 0 {\n\t\t\tindices = append(indices, index)\n\t\t}\n\t}\n\ta.index = indices\n}\n\n// Validate checks if the operation is valid.\nfunc (a *AliasRemoveAction) Validate() error {\n\tvar invalid []string\n\tif len(a.alias) == 0 {\n\t\tinvalid = append(invalid, \"Alias\")\n\t}\n\tif len(a.index) == 0 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Source returns the JSON-serializable data.\nfunc (a *AliasRemoveAction) Source() (interface{}, error) {\n\ta.removeBlankIndexNames()\n\tif err := a.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\tsrc := make(map[string]interface{})\n\tact := make(map[string]interface{})\n\tsrc[\"remove\"] = act\n\tact[\"alias\"] = a.alias\n\tswitch len(a.index) {\n\tcase 1:\n\t\tact[\"index\"] = a.index[0]\n\tdefault:\n\t\tact[\"indices\"] = a.index\n\t}\n\treturn src, nil\n}\n\n// AliasRemoveIndexAction is an action to remove an index during an alias\n// operation.\ntype AliasRemoveIndexAction struct {\n\tindex string // index name\n}\n\n// NewAliasRemoveIndexAction returns an action to remove an index.\nfunc NewAliasRemoveIndexAction(index string) *AliasRemoveIndexAction {\n\treturn &AliasRemoveIndexAction{\n\t\tindex: index,\n\t}\n}\n\n// Validate checks if the operation is valid.\nfunc (a *AliasRemoveIndexAction) Validate() error {\n\tif a.index == \"\" {\n\t\treturn fmt.Errorf(\"missing required field: index\")\n\t}\n\treturn nil\n}\n\n// Source returns the JSON-serializable data.\nfunc (a *AliasRemoveIndexAction) Source() (interface{}, error) {\n\tif err := a.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\tsrc := make(map[string]interface{})\n\tact := make(map[string]interface{})\n\tsrc[\"remove_index\"] = act\n\tact[\"index\"] = a.index\n\treturn src, nil\n}\n\n// -- Service --\n\n// AliasService enables users to add or remove an alias.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-aliases.html\n// for details.\ntype AliasService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tactions []AliasAction\n}\n\n// NewAliasService implements a service to manage aliases.\nfunc NewAliasService(client *Client) *AliasService {\n\tbuilder := &AliasService{\n\t\tclient: client,\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *AliasService) Pretty(pretty bool) *AliasService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *AliasService) Human(human bool) *AliasService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *AliasService) ErrorTrace(errorTrace bool) *AliasService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *AliasService) FilterPath(filterPath ...string) *AliasService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *AliasService) Header(name string, value string) *AliasService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *AliasService) Headers(headers http.Header) *AliasService {\n\ts.headers = headers\n\treturn s\n}\n\n// Add adds an alias to an index.\nfunc (s *AliasService) Add(indexName string, aliasName string) *AliasService {\n\taction := NewAliasAddAction(aliasName).Index(indexName)\n\ts.actions = append(s.actions, action)\n\treturn s\n}\n\n// Add adds an alias to an index and associates a filter to the alias.\nfunc (s *AliasService) AddWithFilter(indexName string, aliasName string, filter Query) *AliasService {\n\taction := NewAliasAddAction(aliasName).Index(indexName).Filter(filter)\n\ts.actions = append(s.actions, action)\n\treturn s\n}\n\n// Remove removes an alias.\nfunc (s *AliasService) Remove(indexName string, aliasName string) *AliasService {\n\taction := NewAliasRemoveAction(aliasName).Index(indexName)\n\ts.actions = append(s.actions, action)\n\treturn s\n}\n\n// Action accepts one or more AliasAction instances which can be\n// of type AliasAddAction or AliasRemoveAction.\nfunc (s *AliasService) Action(action ...AliasAction) *AliasService {\n\ts.actions = append(s.actions, action...)\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *AliasService) buildURL() (string, url.Values, error) {\n\tpath := \"/_aliases\"\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the command.\nfunc (s *AliasService) Do(ctx context.Context) (*AliasResult, error) {\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Body with actions\n\tbody := make(map[string]interface{})\n\tvar actions []interface{}\n\tfor _, action := range s.actions {\n\t\tsrc, err := action.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tactions = append(actions, src)\n\t}\n\tbody[\"actions\"] = actions\n\n\t// Get response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return results\n\tret := new(AliasResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of an alias request.\n\n// AliasResult is the outcome of calling Do on AliasService.\ntype AliasResult struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_put_alias_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nconst (\n\ttestAliasName  = \"elastic-test-alias\"\n\ttestAliasName2 = \"elastic-test-alias2\"\n)\n\nfunc TestAliasLifecycle(t *testing.T) {\n\tvar err error\n\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// Some tweets\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\ttweet3 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\n\t// Add tweets to first index\n\t_, err = client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Add tweets to second index\n\t_, err = client.Index().Index(testIndexName2).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Refresh\n\t_, err = client.Refresh().Index(testIndexName, testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Add both indices to a new alias\n\taliasCreate, err := client.Alias().\n\t\tAdd(testIndexName, testAliasName).\n\t\tAction(NewAliasAddAction(testAliasName).Index(testIndexName2)).\n\t\t//Pretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !aliasCreate.Acknowledged {\n\t\tt.Errorf(\"expected AliasResult.Acknowledged %v; got %v\", true, aliasCreate.Acknowledged)\n\t}\n\n\t// Search should return all 3 tweets\n\tmatchAll := NewMatchAllQuery()\n\tsearchResult1, err := client.Search().Index(testAliasName).Query(matchAll).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult1.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult1.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult1.TotalHits())\n\t}\n\n\t// Remove first index should remove two tweets, so should only yield 1\n\taliasRemove1, err := client.Alias().\n\t\tRemove(testIndexName, testAliasName).\n\t\t//Pretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !aliasRemove1.Acknowledged {\n\t\tt.Errorf(\"expected AliasResult.Acknowledged %v; got %v\", true, aliasRemove1.Acknowledged)\n\t}\n\n\tsearchResult2, err := client.Search().Index(testAliasName).Query(matchAll).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult2.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult2.TotalHits() != 1 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 1, searchResult2.TotalHits())\n\t}\n\n\t// Add second index back to alias as write index\n\taliasCreate, err = client.Alias().\n\t\tAction(NewAliasAddAction(testAliasName).Index(testIndexName).IsWriteIndex(false)).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !aliasCreate.Acknowledged {\n\t\tt.Errorf(\"expected AliasResult.Acknowledged %v; got %v\", true, aliasCreate.Acknowledged)\n\t}\n\taliasCreate, err = client.Alias().\n\t\tAction(NewAliasAddAction(testAliasName).Index(testIndexName2).IsWriteIndex(true)).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !aliasCreate.Acknowledged {\n\t\tt.Errorf(\"expected AliasResult.Acknowledged %v; got %v\", true, aliasCreate.Acknowledged)\n\t}\n\n\t_, err = client.Aliases().Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\ttweet4 := tweet{User: \"chris\", Message: \"Foo bar baz.\"}\n\t_, err = client.Index().Index(testAliasName).Id(\"4\").BodyJson(&tweet4).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName, testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tsearchResult3, err := client.Search().Index(testIndexName2).Query(NewIdsQuery().Ids(\"4\")).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult3.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult3.TotalHits() != 1 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 1, searchResult3.TotalHits())\n\t}\n}\n\nfunc TestAliasAddAction(t *testing.T) {\n\tvar tests = []struct {\n\t\tAction   *AliasAddAction\n\t\tExpected string\n\t\tInvalid  bool\n\t}{\n\t\t{\n\t\t\tAction:  NewAliasAddAction(\"\").Index(\"\"),\n\t\t\tInvalid: true,\n\t\t},\n\t\t{\n\t\t\tAction:  NewAliasAddAction(\"alias1\").Index(\"\"),\n\t\t\tInvalid: true,\n\t\t},\n\t\t{\n\t\t\tAction:  NewAliasAddAction(\"\").Index(\"index1\"),\n\t\t\tInvalid: true,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasAddAction(\"alias1\").Index(\"index1\"),\n\t\t\tExpected: `{\"add\":{\"alias\":\"alias1\",\"index\":\"index1\"}}`,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasAddAction(\"alias1\").Index(\"index1\", \"index2\"),\n\t\t\tExpected: `{\"add\":{\"alias\":\"alias1\",\"indices\":[\"index1\",\"index2\"]}}`,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasAddAction(\"alias1\").Index(\"index1\").Routing(\"routing1\"),\n\t\t\tExpected: `{\"add\":{\"alias\":\"alias1\",\"index\":\"index1\",\"routing\":\"routing1\"}}`,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasAddAction(\"alias1\").Index(\"index1\").Routing(\"routing1\").IndexRouting(\"indexRouting1\"),\n\t\t\tExpected: `{\"add\":{\"alias\":\"alias1\",\"index\":\"index1\",\"index_routing\":\"indexRouting1\",\"routing\":\"routing1\"}}`,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasAddAction(\"alias1\").Index(\"index1\").Routing(\"routing1\").SearchRouting(\"searchRouting1\"),\n\t\t\tExpected: `{\"add\":{\"alias\":\"alias1\",\"index\":\"index1\",\"routing\":\"routing1\",\"search_routing\":\"searchRouting1\"}}`,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasAddAction(\"alias1\").Index(\"index1\").Routing(\"routing1\").SearchRouting(\"searchRouting1\", \"searchRouting2\"),\n\t\t\tExpected: `{\"add\":{\"alias\":\"alias1\",\"index\":\"index1\",\"routing\":\"routing1\",\"search_routing\":\"searchRouting1,searchRouting2\"}}`,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasAddAction(\"alias1\").Index(\"index1\").Filter(NewTermQuery(\"user\", \"olivere\")),\n\t\t\tExpected: `{\"add\":{\"alias\":\"alias1\",\"filter\":{\"term\":{\"user\":\"olivere\"}},\"index\":\"index1\"}}`,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tsrc, err := tt.Action.Source()\n\t\tif err != nil {\n\t\t\tif !tt.Invalid {\n\t\t\t\tt.Errorf(\"#%d: expected to succeed\", i)\n\t\t\t}\n\t\t} else {\n\t\t\tif tt.Invalid {\n\t\t\t\tt.Errorf(\"#%d: expected to fail\", i)\n\t\t\t} else {\n\t\t\t\tdst, err := json.Marshal(src)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif want, have := tt.Expected, string(dst); want != have {\n\t\t\t\t\tt.Errorf(\"#%d: expected %s, got %s\", i, want, have)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestAliasRemoveAction(t *testing.T) {\n\tvar tests = []struct {\n\t\tAction   *AliasRemoveAction\n\t\tExpected string\n\t\tInvalid  bool\n\t}{\n\t\t{\n\t\t\tAction:  NewAliasRemoveAction(\"\"),\n\t\t\tInvalid: true,\n\t\t},\n\t\t{\n\t\t\tAction:  NewAliasRemoveAction(\"alias1\"),\n\t\t\tInvalid: true,\n\t\t},\n\t\t{\n\t\t\tAction:  NewAliasRemoveAction(\"\").Index(\"index1\"),\n\t\t\tInvalid: true,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasRemoveAction(\"alias1\").Index(\"index1\"),\n\t\t\tExpected: `{\"remove\":{\"alias\":\"alias1\",\"index\":\"index1\"}}`,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasRemoveAction(\"alias1\").Index(\"index1\", \"index2\"),\n\t\t\tExpected: `{\"remove\":{\"alias\":\"alias1\",\"indices\":[\"index1\",\"index2\"]}}`,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tsrc, err := tt.Action.Source()\n\t\tif err != nil {\n\t\t\tif !tt.Invalid {\n\t\t\t\tt.Errorf(\"#%d: expected to succeed\", i)\n\t\t\t}\n\t\t} else {\n\t\t\tif tt.Invalid {\n\t\t\t\tt.Errorf(\"#%d: expected to fail\", i)\n\t\t\t} else {\n\t\t\t\tdst, err := json.Marshal(src)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif want, have := tt.Expected, string(dst); want != have {\n\t\t\t\t\tt.Errorf(\"#%d: expected %s, got %s\", i, want, have)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestAliasRemoveIndexAction(t *testing.T) {\n\tvar tests = []struct {\n\t\tAction   *AliasRemoveIndexAction\n\t\tExpected string\n\t\tInvalid  bool\n\t}{\n\t\t{\n\t\t\tAction:  NewAliasRemoveIndexAction(\"\"),\n\t\t\tInvalid: true,\n\t\t},\n\t\t{\n\t\t\tAction:   NewAliasRemoveIndexAction(\"index1\"),\n\t\t\tExpected: `{\"remove_index\":{\"index\":\"index1\"}}`,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tsrc, err := tt.Action.Source()\n\t\tif err != nil {\n\t\t\tif !tt.Invalid {\n\t\t\t\tt.Errorf(\"#%d: expected to succeed\", i)\n\t\t\t}\n\t\t} else {\n\t\t\tif tt.Invalid {\n\t\t\t\tt.Errorf(\"#%d: expected to fail\", i)\n\t\t\t} else {\n\t\t\t\tdst, err := json.Marshal(src)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatal(err)\n\t\t\t\t}\n\t\t\t\tif want, have := tt.Expected, string(dst); want != have {\n\t\t\t\t\tt.Errorf(\"#%d: expected %s, got %s\", i, want, have)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_put_component_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesPutComponentTemplateService creates or updates component templates.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-component-template.html\n// for more details on this API.\ntype IndicesPutComponentTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname          string\n\tcreate        *bool\n\tcause         string\n\tmasterTimeout string\n\n\tbodyJson   interface{}\n\tbodyString string\n}\n\n// NewIndicesPutComponentTemplateService creates a new IndicesPutComponentTemplateService.\nfunc NewIndicesPutComponentTemplateService(client *Client) *IndicesPutComponentTemplateService {\n\treturn &IndicesPutComponentTemplateService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesPutComponentTemplateService) Pretty(pretty bool) *IndicesPutComponentTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesPutComponentTemplateService) Human(human bool) *IndicesPutComponentTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesPutComponentTemplateService) ErrorTrace(errorTrace bool) *IndicesPutComponentTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesPutComponentTemplateService) FilterPath(filterPath ...string) *IndicesPutComponentTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesPutComponentTemplateService) Header(name string, value string) *IndicesPutComponentTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesPutComponentTemplateService) Headers(headers http.Header) *IndicesPutComponentTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the component template.\nfunc (s *IndicesPutComponentTemplateService) Name(name string) *IndicesPutComponentTemplateService {\n\ts.name = name\n\treturn s\n}\n\n// Create indicates whether the component template should only be added if\n// new or can also replace an existing one.\nfunc (s *IndicesPutComponentTemplateService) Create(create bool) *IndicesPutComponentTemplateService {\n\ts.create = &create\n\treturn s\n}\n\n// Cause is the user-defined reason for creating/updating the the component template.\nfunc (s *IndicesPutComponentTemplateService) Cause(cause string) *IndicesPutComponentTemplateService {\n\ts.cause = cause\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesPutComponentTemplateService) MasterTimeout(masterTimeout string) *IndicesPutComponentTemplateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// BodyJson is the component template definition as a JSON serializable\n// type, e.g. map[string]interface{}.\nfunc (s *IndicesPutComponentTemplateService) BodyJson(body interface{}) *IndicesPutComponentTemplateService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the component template definition as a raw string.\nfunc (s *IndicesPutComponentTemplateService) BodyString(body string) *IndicesPutComponentTemplateService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesPutComponentTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_component_template/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.create != nil {\n\t\tparams.Set(\"create\", fmt.Sprint(*s.create))\n\t}\n\tif s.cause != \"\" {\n\t\tparams.Set(\"cause\", s.cause)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesPutComponentTemplateService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif s.bodyString == \"\" && s.bodyJson == nil {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesPutComponentTemplateService) Do(ctx context.Context) (*IndicesPutComponentTemplateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesPutComponentTemplateResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesPutComponentTemplateResponse is the response of IndicesPutComponentTemplateService.Do.\ntype IndicesPutComponentTemplateResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_put_index_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesPutIndexTemplateService creates or updates index templates.\n//\n// Index templates have changed during in 7.8 update of Elasticsearch.\n// This service implements the new version (7.8 or higher) for managing\n// index templates. If you want the v1/legacy version, please see e.g.\n// IndicesPutTemplateService and friends.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-put-template.html\n// for more details on this API.\ntype IndicesPutIndexTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname          string\n\tcreate        *bool\n\tcause         string\n\tmasterTimeout string\n\n\tbodyJson   interface{}\n\tbodyString string\n}\n\n// NewIndicesPutIndexTemplateService creates a new IndicesPutIndexTemplateService.\nfunc NewIndicesPutIndexTemplateService(client *Client) *IndicesPutIndexTemplateService {\n\treturn &IndicesPutIndexTemplateService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesPutIndexTemplateService) Pretty(pretty bool) *IndicesPutIndexTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesPutIndexTemplateService) Human(human bool) *IndicesPutIndexTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesPutIndexTemplateService) ErrorTrace(errorTrace bool) *IndicesPutIndexTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesPutIndexTemplateService) FilterPath(filterPath ...string) *IndicesPutIndexTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesPutIndexTemplateService) Header(name string, value string) *IndicesPutIndexTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesPutIndexTemplateService) Headers(headers http.Header) *IndicesPutIndexTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the index template.\nfunc (s *IndicesPutIndexTemplateService) Name(name string) *IndicesPutIndexTemplateService {\n\ts.name = name\n\treturn s\n}\n\n// Create indicates whether the index template should only be added if\n// new or can also replace an existing one.\nfunc (s *IndicesPutIndexTemplateService) Create(create bool) *IndicesPutIndexTemplateService {\n\ts.create = &create\n\treturn s\n}\n\n// Cause is the user-defined reason for creating/updating the the index template.\nfunc (s *IndicesPutIndexTemplateService) Cause(cause string) *IndicesPutIndexTemplateService {\n\ts.cause = cause\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesPutIndexTemplateService) MasterTimeout(masterTimeout string) *IndicesPutIndexTemplateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// BodyJson is the index template definition as a JSON serializable\n// type, e.g. map[string]interface{}.\nfunc (s *IndicesPutIndexTemplateService) BodyJson(body interface{}) *IndicesPutIndexTemplateService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the index template definition as a raw string.\nfunc (s *IndicesPutIndexTemplateService) BodyString(body string) *IndicesPutIndexTemplateService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesPutIndexTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_index_template/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.create != nil {\n\t\tparams.Set(\"create\", fmt.Sprint(*s.create))\n\t}\n\tif s.cause != \"\" {\n\t\tparams.Set(\"cause\", s.cause)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesPutIndexTemplateService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif s.bodyString == \"\" && s.bodyJson == nil {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesPutIndexTemplateService) Do(ctx context.Context) (*IndicesPutIndexTemplateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesPutIndexTemplateResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesPutIndexTemplateResponse is the response of IndicesPutIndexTemplateService.Do.\ntype IndicesPutIndexTemplateResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_put_mapping.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesPutMappingService allows to register specific mapping definition\n// for a specific type.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-put-mapping.html\n// for details.\ntype IndicesPutMappingService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tmasterTimeout     string\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n\tincludeTypeName   *bool\n\twriteIndexOnly    *bool\n\ttimeout           string\n\tbodyJson          map[string]interface{}\n\tbodyString        string\n}\n\n// NewPutMappingService is an alias for NewIndicesPutMappingService.\n// Use NewIndicesPutMappingService.\nfunc NewPutMappingService(client *Client) *IndicesPutMappingService {\n\treturn NewIndicesPutMappingService(client)\n}\n\n// NewIndicesPutMappingService creates a new IndicesPutMappingService.\nfunc NewIndicesPutMappingService(client *Client) *IndicesPutMappingService {\n\treturn &IndicesPutMappingService{\n\t\tclient: client,\n\t\tindex:  make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesPutMappingService) Pretty(pretty bool) *IndicesPutMappingService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesPutMappingService) Human(human bool) *IndicesPutMappingService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesPutMappingService) ErrorTrace(errorTrace bool) *IndicesPutMappingService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesPutMappingService) FilterPath(filterPath ...string) *IndicesPutMappingService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesPutMappingService) Header(name string, value string) *IndicesPutMappingService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesPutMappingService) Headers(headers http.Header) *IndicesPutMappingService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names the mapping should be added to\n// (supports wildcards); use `_all` or omit to add the mapping on all indices.\nfunc (s *IndicesPutMappingService) Index(indices ...string) *IndicesPutMappingService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndicesPutMappingService) Timeout(timeout string) *IndicesPutMappingService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesPutMappingService) MasterTimeout(masterTimeout string) *IndicesPutMappingService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesPutMappingService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesPutMappingService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices.\n// This includes `_all` string or when no indices have been specified.\nfunc (s *IndicesPutMappingService) AllowNoIndices(allowNoIndices bool) *IndicesPutMappingService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *IndicesPutMappingService) ExpandWildcards(expandWildcards string) *IndicesPutMappingService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// IncludeTypeName indicates whether a type should be expected in the body of the mappings.\nfunc (s *IndicesPutMappingService) IncludeTypeName(includeTypeName bool) *IndicesPutMappingService {\n\ts.includeTypeName = &includeTypeName\n\treturn s\n}\n\n// WriteIndexOnly, when true, applies mappings only to the write index of an alias or data stream.\nfunc (s *IndicesPutMappingService) WriteIndexOnly(writeIndexOnly bool) *IndicesPutMappingService {\n\ts.writeIndexOnly = &writeIndexOnly\n\treturn s\n}\n\n// BodyJson contains the mapping definition.\nfunc (s *IndicesPutMappingService) BodyJson(mapping map[string]interface{}) *IndicesPutMappingService {\n\ts.bodyJson = mapping\n\treturn s\n}\n\n// BodyString is the mapping definition serialized as a string.\nfunc (s *IndicesPutMappingService) BodyString(mapping string) *IndicesPutMappingService {\n\ts.bodyString = mapping\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesPutMappingService) buildURL() (string, url.Values, error) {\n\tpath, err := uritemplates.Expand(\"/{index}/_mapping\", map[string]string{\n\t\t\"index\": strings.Join(s.index, \",\"),\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprint(*s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.includeTypeName != nil {\n\t\tparams.Set(\"include_type_name\", fmt.Sprint(*s.includeTypeName))\n\t}\n\tif s.writeIndexOnly != nil {\n\t\tparams.Set(\"write_index_only\", fmt.Sprint(*s.writeIndexOnly))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesPutMappingService) Validate() error {\n\tvar invalid []string\n\tif len(s.index) == 0 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif s.bodyString == \"\" && s.bodyJson == nil {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesPutMappingService) Do(ctx context.Context) (*PutMappingResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(PutMappingResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// PutMappingResponse is the response of IndicesPutMappingService.Do.\ntype PutMappingResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_put_mapping_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestPutMappingURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{\"*\"},\n\t\t\t\"/%2A/_mapping\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"store-1\", \"store-2\"},\n\t\t\t\"/store-1%2Cstore-2/_mapping\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.PutMapping().Index(test.Indices...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestMappingLifecycle(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\t//client := setupTestClientAndCreateIndexAndLog(t)\n\n\t// Create index\n\tcreateIndex, err := client.CreateIndex(testIndexName3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndex)\n\t}\n\n\tmapping := `{\n\t\t\"properties\":{\n\t\t\t\"field\":{\n\t\t\t\t\"type\":\"keyword\"\n\t\t\t}\n\t\t}\n\t}`\n\n\tputresp, err := client.PutMapping().Index(testIndexName3).BodyString(mapping).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected put mapping to succeed; got: %v\", err)\n\t}\n\tif putresp == nil {\n\t\tt.Fatalf(\"expected put mapping response; got: %v\", putresp)\n\t}\n\tif !putresp.Acknowledged {\n\t\tt.Fatalf(\"expected put mapping ack; got: %v\", putresp.Acknowledged)\n\t}\n\n\tgetresp, err := client.GetMapping().Index(testIndexName3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected get mapping to succeed; got: %v\", err)\n\t}\n\tif getresp == nil {\n\t\tt.Fatalf(\"expected get mapping response; got: %v\", getresp)\n\t}\n\tprops, ok := getresp[testIndexName3]\n\tif !ok {\n\t\tt.Fatalf(\"expected JSON root to be of type map[string]interface{}; got: %#v\", props)\n\t}\n\n\t// NOTE There is no Delete Mapping API in Elasticsearch 2.0\n}\n"
  },
  {
    "path": "indices_put_settings.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesPutSettingsService changes specific index level settings in\n// real time.\n//\n// See the documentation at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-update-settings.html.\ntype IndicesPutSettingsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tallowNoIndices    *bool\n\texpandWildcards   string\n\tflatSettings      *bool\n\tignoreUnavailable *bool\n\tmasterTimeout     string\n\tbodyJson          interface{}\n\tbodyString        string\n}\n\n// NewIndicesPutSettingsService creates a new IndicesPutSettingsService.\nfunc NewIndicesPutSettingsService(client *Client) *IndicesPutSettingsService {\n\treturn &IndicesPutSettingsService{\n\t\tclient: client,\n\t\tindex:  make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesPutSettingsService) Pretty(pretty bool) *IndicesPutSettingsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesPutSettingsService) Human(human bool) *IndicesPutSettingsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesPutSettingsService) ErrorTrace(errorTrace bool) *IndicesPutSettingsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesPutSettingsService) FilterPath(filterPath ...string) *IndicesPutSettingsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesPutSettingsService) Header(name string, value string) *IndicesPutSettingsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesPutSettingsService) Headers(headers http.Header) *IndicesPutSettingsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names the mapping should be added to\n// (supports wildcards); use `_all` or omit to add the mapping on all indices.\nfunc (s *IndicesPutSettingsService) Index(indices ...string) *IndicesPutSettingsService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes `_all`\n// string or when no indices have been specified).\nfunc (s *IndicesPutSettingsService) AllowNoIndices(allowNoIndices bool) *IndicesPutSettingsService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards specifies whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *IndicesPutSettingsService) ExpandWildcards(expandWildcards string) *IndicesPutSettingsService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// FlatSettings indicates whether to return settings in flat format (default: false).\nfunc (s *IndicesPutSettingsService) FlatSettings(flatSettings bool) *IndicesPutSettingsService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// IgnoreUnavailable specifies whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesPutSettingsService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesPutSettingsService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// MasterTimeout is the timeout for connection to master.\nfunc (s *IndicesPutSettingsService) MasterTimeout(masterTimeout string) *IndicesPutSettingsService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// BodyJson is documented as: The index settings to be updated.\nfunc (s *IndicesPutSettingsService) BodyJson(body interface{}) *IndicesPutSettingsService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is documented as: The index settings to be updated.\nfunc (s *IndicesPutSettingsService) BodyString(body string) *IndicesPutSettingsService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesPutSettingsService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_settings\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_settings\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprintf(\"%v\", *s.flatSettings))\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesPutSettingsService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesPutSettingsService) Do(ctx context.Context) (*IndicesPutSettingsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesPutSettingsResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesPutSettingsResponse is the response of IndicesPutSettingsService.Do.\ntype IndicesPutSettingsResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_put_settings_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesPutSettingsBuildURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t\"/_settings\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"*\"},\n\t\t\t\"/%2A/_settings\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"store-1\", \"store-2\"},\n\t\t\t\"/store-1%2Cstore-2/_settings\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.IndexPutSettings().Index(test.Indices...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndicesSettingsLifecycle(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tbody := `{\n\t\t\"index\":{\n\t\t\t\"refresh_interval\":\"-1\"\n\t\t}\n\t}`\n\n\t// Put settings\n\tputres, err := client.IndexPutSettings().Index(testIndexName).BodyString(body).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected put settings to succeed; got: %v\", err)\n\t}\n\tif putres == nil {\n\t\tt.Fatalf(\"expected put settings response; got: %v\", putres)\n\t}\n\tif !putres.Acknowledged {\n\t\tt.Fatalf(\"expected put settings ack; got: %v\", putres.Acknowledged)\n\t}\n\n\t// Read settings\n\tgetres, err := client.IndexGetSettings().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected get mapping to succeed; got: %v\", err)\n\t}\n\tif getres == nil {\n\t\tt.Fatalf(\"expected get mapping response; got: %v\", getres)\n\t}\n\n\t// Check settings\n\tindex, found := getres[testIndexName]\n\tif !found {\n\t\tt.Fatalf(\"expected to return settings for index %q; got: %#v\", testIndexName, getres)\n\t}\n\t// Retrieve \"index\" section of the settings for index testIndexName\n\tsectionIntf, ok := index.Settings[\"index\"]\n\tif !ok {\n\t\tt.Fatalf(\"expected settings to have %q field; got: %#v\", \"index\", getres)\n\t}\n\tsection, ok := sectionIntf.(map[string]interface{})\n\tif !ok {\n\t\tt.Fatalf(\"expected settings to be of type map[string]interface{}; got: %#v\", getres)\n\t}\n\trefintv, ok := section[\"refresh_interval\"]\n\tif !ok {\n\t\tt.Fatalf(`expected JSON to include \"refresh_interval\" field; got: %#v`, getres)\n\t}\n\tif got, want := refintv, \"-1\"; got != want {\n\t\tt.Fatalf(\"expected refresh_interval = %v; got: %v\", want, got)\n\t}\n}\n"
  },
  {
    "path": "indices_put_template.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesPutTemplateService creates or updates templates.\n//\n// Index templates have changed during in 7.8 update of Elasticsearch.\n// This service implements the legacy version (7.7 or lower). If you want\n// the new version, please use the IndicesPutIndexTemplateService.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-templates-v1.html\n// for more details.\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\ntype IndicesPutTemplateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname            string\n\tcause           string\n\torder           interface{}\n\tversion         *int\n\tcreate          *bool\n\ttimeout         string\n\tmasterTimeout   string\n\tflatSettings    *bool\n\tincludeTypeName *bool\n\tbodyJson        interface{}\n\tbodyString      string\n}\n\n// NewIndicesPutTemplateService creates a new IndicesPutTemplateService.\nfunc NewIndicesPutTemplateService(client *Client) *IndicesPutTemplateService {\n\treturn &IndicesPutTemplateService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesPutTemplateService) Pretty(pretty bool) *IndicesPutTemplateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesPutTemplateService) Human(human bool) *IndicesPutTemplateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesPutTemplateService) ErrorTrace(errorTrace bool) *IndicesPutTemplateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesPutTemplateService) FilterPath(filterPath ...string) *IndicesPutTemplateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesPutTemplateService) Header(name string, value string) *IndicesPutTemplateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesPutTemplateService) Headers(headers http.Header) *IndicesPutTemplateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is the name of the index template.\nfunc (s *IndicesPutTemplateService) Name(name string) *IndicesPutTemplateService {\n\ts.name = name\n\treturn s\n}\n\n// Cause describes the cause for this index template creation. This is currently\n// undocumented, but part of the Java source.\nfunc (s *IndicesPutTemplateService) Cause(cause string) *IndicesPutTemplateService {\n\ts.cause = cause\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndicesPutTemplateService) Timeout(timeout string) *IndicesPutTemplateService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesPutTemplateService) MasterTimeout(masterTimeout string) *IndicesPutTemplateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IncludeTypeName indicates whether a type should be expected in the body of the mappings.\nfunc (s *IndicesPutTemplateService) IncludeTypeName(includeTypeName bool) *IndicesPutTemplateService {\n\ts.includeTypeName = &includeTypeName\n\treturn s\n}\n\n// FlatSettings indicates whether to return settings in flat format (default: false).\nfunc (s *IndicesPutTemplateService) FlatSettings(flatSettings bool) *IndicesPutTemplateService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// Order is the order for this template when merging multiple matching ones\n// (higher numbers are merged later, overriding the lower numbers).\nfunc (s *IndicesPutTemplateService) Order(order interface{}) *IndicesPutTemplateService {\n\ts.order = order\n\treturn s\n}\n\n// Version sets the version number for this template.\nfunc (s *IndicesPutTemplateService) Version(version int) *IndicesPutTemplateService {\n\ts.version = &version\n\treturn s\n}\n\n// Create indicates whether the index template should only be added if\n// new or can also replace an existing one.\nfunc (s *IndicesPutTemplateService) Create(create bool) *IndicesPutTemplateService {\n\ts.create = &create\n\treturn s\n}\n\n// BodyJson is documented as: The template definition.\nfunc (s *IndicesPutTemplateService) BodyJson(body interface{}) *IndicesPutTemplateService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is documented as: The template definition.\nfunc (s *IndicesPutTemplateService) BodyString(body string) *IndicesPutTemplateService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesPutTemplateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_template/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.order != nil {\n\t\tparams.Set(\"order\", fmt.Sprintf(\"%v\", s.order))\n\t}\n\tif s.version != nil {\n\t\tparams.Set(\"version\", fmt.Sprint(*s.version))\n\t}\n\tif s.create != nil {\n\t\tparams.Set(\"create\", fmt.Sprint(*s.create))\n\t}\n\tif s.cause != \"\" {\n\t\tparams.Set(\"cause\", s.cause)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprint(*s.flatSettings))\n\t}\n\tif s.includeTypeName != nil {\n\t\tparams.Set(\"include_type_name\", fmt.Sprint(*s.includeTypeName))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesPutTemplateService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif s.bodyString == \"\" && s.bodyJson == nil {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\n//\n// Deprecated: Legacy index templates are deprecated in favor of composable templates.\nfunc (s *IndicesPutTemplateService) Do(ctx context.Context) (*IndicesPutTemplateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesPutTemplateResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesPutTemplateResponse is the response of IndicesPutTemplateService.Do.\ntype IndicesPutTemplateResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_refresh.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// RefreshService explicitly refreshes one or more indices.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-refresh.html.\ntype RefreshService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex []string\n}\n\n// NewRefreshService creates a new instance of RefreshService.\nfunc NewRefreshService(client *Client) *RefreshService {\n\tbuilder := &RefreshService{\n\t\tclient: client,\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *RefreshService) Pretty(pretty bool) *RefreshService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *RefreshService) Human(human bool) *RefreshService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *RefreshService) ErrorTrace(errorTrace bool) *RefreshService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *RefreshService) FilterPath(filterPath ...string) *RefreshService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *RefreshService) Header(name string, value string) *RefreshService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *RefreshService) Headers(headers http.Header) *RefreshService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index specifies the indices to refresh.\nfunc (s *RefreshService) Index(index ...string) *RefreshService {\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *RefreshService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_refresh\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_refresh\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Do executes the request.\nfunc (s *RefreshService) Do(ctx context.Context) (*RefreshResult, error) {\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return result\n\tret := new(RefreshResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Result of a refresh request.\n\n// RefreshResult is the outcome of RefreshService.Do.\ntype RefreshResult struct {\n\tBroadcastResponse\n}\n"
  },
  {
    "path": "indices_refresh_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestRefreshBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t\"/_refresh\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t\"/index1/_refresh\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t\"/index1%2Cindex2/_refresh\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.Refresh().Index(test.Indices...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestRefresh(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add some documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Flush().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Refresh indices\n\tres, err := client.Refresh(testIndexName, testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected result; got nil\")\n\t}\n}\n"
  },
  {
    "path": "indices_rollover.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesRolloverService rolls an alias over to a new index when the\n// existing index is considered to be too large or too old.\n//\n// It is documented at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-rollover-index.html.\ntype IndicesRolloverService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tdryRun              bool\n\tnewIndex            string\n\talias               string\n\tmasterTimeout       string\n\ttimeout             string\n\twaitForActiveShards string\n\tconditions          map[string]interface{}\n\tsettings            map[string]interface{}\n\tmappings            map[string]interface{}\n\tbodyJson            interface{}\n\tbodyString          string\n}\n\n// NewIndicesRolloverService creates a new IndicesRolloverService.\nfunc NewIndicesRolloverService(client *Client) *IndicesRolloverService {\n\treturn &IndicesRolloverService{\n\t\tclient:     client,\n\t\tconditions: make(map[string]interface{}),\n\t\tsettings:   make(map[string]interface{}),\n\t\tmappings:   make(map[string]interface{}),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesRolloverService) Pretty(pretty bool) *IndicesRolloverService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesRolloverService) Human(human bool) *IndicesRolloverService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesRolloverService) ErrorTrace(errorTrace bool) *IndicesRolloverService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesRolloverService) FilterPath(filterPath ...string) *IndicesRolloverService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesRolloverService) Header(name string, value string) *IndicesRolloverService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesRolloverService) Headers(headers http.Header) *IndicesRolloverService {\n\ts.headers = headers\n\treturn s\n}\n\n// Alias is the name of the alias to rollover.\nfunc (s *IndicesRolloverService) Alias(alias string) *IndicesRolloverService {\n\ts.alias = alias\n\treturn s\n}\n\n// NewIndex is the name of the rollover index.\nfunc (s *IndicesRolloverService) NewIndex(newIndex string) *IndicesRolloverService {\n\ts.newIndex = newIndex\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesRolloverService) MasterTimeout(masterTimeout string) *IndicesRolloverService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Timeout sets an explicit operation timeout.\nfunc (s *IndicesRolloverService) Timeout(timeout string) *IndicesRolloverService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// WaitForActiveShards sets the number of active shards to wait for on the\n// newly created rollover index before the operation returns.\nfunc (s *IndicesRolloverService) WaitForActiveShards(waitForActiveShards string) *IndicesRolloverService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// DryRun, when set, specifies that only conditions are checked without\n// performing the actual rollover.\nfunc (s *IndicesRolloverService) DryRun(dryRun bool) *IndicesRolloverService {\n\ts.dryRun = dryRun\n\treturn s\n}\n\n// Conditions allows to specify all conditions as a dictionary.\nfunc (s *IndicesRolloverService) Conditions(conditions map[string]interface{}) *IndicesRolloverService {\n\ts.conditions = conditions\n\treturn s\n}\n\n// AddCondition adds a condition to the rollover decision.\nfunc (s *IndicesRolloverService) AddCondition(name string, value interface{}) *IndicesRolloverService {\n\ts.conditions[name] = value\n\treturn s\n}\n\n// AddMaxIndexAgeCondition adds a condition to set the max index age.\nfunc (s *IndicesRolloverService) AddMaxIndexAgeCondition(time string) *IndicesRolloverService {\n\ts.conditions[\"max_age\"] = time\n\treturn s\n}\n\n// AddMaxIndexDocsCondition adds a condition to set the max documents in the index.\nfunc (s *IndicesRolloverService) AddMaxIndexDocsCondition(docs int64) *IndicesRolloverService {\n\ts.conditions[\"max_docs\"] = docs\n\treturn s\n}\n\n// Settings adds the index settings.\nfunc (s *IndicesRolloverService) Settings(settings map[string]interface{}) *IndicesRolloverService {\n\ts.settings = settings\n\treturn s\n}\n\n// AddSetting adds an index setting.\nfunc (s *IndicesRolloverService) AddSetting(name string, value interface{}) *IndicesRolloverService {\n\ts.settings[name] = value\n\treturn s\n}\n\n// Mappings adds the index mappings.\nfunc (s *IndicesRolloverService) Mappings(mappings map[string]interface{}) *IndicesRolloverService {\n\ts.mappings = mappings\n\treturn s\n}\n\n// AddMapping adds a mapping for the given type.\nfunc (s *IndicesRolloverService) AddMapping(typ string, mapping interface{}) *IndicesRolloverService {\n\ts.mappings[typ] = mapping\n\treturn s\n}\n\n// BodyJson sets the conditions that needs to be met for executing rollover,\n// specified as a serializable JSON instance which is sent as the body of\n// the request.\nfunc (s *IndicesRolloverService) BodyJson(body interface{}) *IndicesRolloverService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString sets the conditions that needs to be met for executing rollover,\n// specified as a string which is sent as the body of the request.\nfunc (s *IndicesRolloverService) BodyString(body string) *IndicesRolloverService {\n\ts.bodyString = body\n\treturn s\n}\n\n// getBody returns the body of the request, if not explicitly set via\n// BodyJson or BodyString.\nfunc (s *IndicesRolloverService) getBody() interface{} {\n\tbody := make(map[string]interface{})\n\tif len(s.conditions) > 0 {\n\t\tbody[\"conditions\"] = s.conditions\n\t}\n\tif len(s.settings) > 0 {\n\t\tbody[\"settings\"] = s.settings\n\t}\n\tif len(s.mappings) > 0 {\n\t\tbody[\"mappings\"] = s.mappings\n\t}\n\treturn body\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesRolloverService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif s.newIndex != \"\" {\n\t\tpath, err = uritemplates.Expand(\"/{alias}/_rollover/{new_index}\", map[string]string{\n\t\t\t\"alias\":     s.alias,\n\t\t\t\"new_index\": s.newIndex,\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/{alias}/_rollover\", map[string]string{\n\t\t\t\"alias\": s.alias,\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.dryRun {\n\t\tparams.Set(\"dry_run\", \"true\")\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesRolloverService) Validate() error {\n\tvar invalid []string\n\tif s.alias == \"\" {\n\t\tinvalid = append(invalid, \"Alias\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesRolloverService) Do(ctx context.Context) (*IndicesRolloverResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else if s.bodyString != \"\" {\n\t\tbody = s.bodyString\n\t} else {\n\t\tbody = s.getBody()\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesRolloverResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesRolloverResponse is the response of IndicesRolloverService.Do.\ntype IndicesRolloverResponse struct {\n\tOldIndex           string          `json:\"old_index\"`\n\tNewIndex           string          `json:\"new_index\"`\n\tRolledOver         bool            `json:\"rolled_over\"`\n\tDryRun             bool            `json:\"dry_run\"`\n\tAcknowledged       bool            `json:\"acknowledged\"`\n\tShardsAcknowledged bool            `json:\"shards_acknowledged\"`\n\tConditions         map[string]bool `json:\"conditions\"`\n}\n"
  },
  {
    "path": "indices_rollover_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestIndicesRolloverBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tAlias    string\n\t\tNewIndex string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"logs_write\",\n\t\t\t\"\",\n\t\t\t\"/logs_write/_rollover\",\n\t\t},\n\t\t{\n\t\t\t\"logs_write\",\n\t\t\t\"my_new_index_name\",\n\t\t\t\"/logs_write/_rollover/my_new_index_name\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.RolloverIndex(test.Alias).NewIndex(test.NewIndex).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndicesRolloverBodyConditions(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsvc := NewIndicesRolloverService(client).\n\t\tConditions(map[string]interface{}{\n\t\t\t\"max_age\":  \"7d\",\n\t\t\t\"max_docs\": 1000,\n\t\t})\n\tdata, err := json.Marshal(svc.getBody())\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"conditions\":{\"max_age\":\"7d\",\"max_docs\":1000}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestIndicesRolloverBodyAddCondition(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsvc := NewIndicesRolloverService(client).\n\t\tAddCondition(\"max_age\", \"7d\").\n\t\tAddCondition(\"max_docs\", 1000)\n\tdata, err := json.Marshal(svc.getBody())\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"conditions\":{\"max_age\":\"7d\",\"max_docs\":1000}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestIndicesRolloverBodyAddPredefinedConditions(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsvc := NewIndicesRolloverService(client).\n\t\tAddMaxIndexAgeCondition(\"2d\").\n\t\tAddMaxIndexDocsCondition(1000000)\n\tdata, err := json.Marshal(svc.getBody())\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"conditions\":{\"max_age\":\"2d\",\"max_docs\":1000000}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestIndicesRolloverBodyComplex(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsvc := NewIndicesRolloverService(client).\n\t\tAddMaxIndexAgeCondition(\"2d\").\n\t\tAddMaxIndexDocsCondition(1000000).\n\t\tAddSetting(\"index.number_of_shards\", 2).\n\t\tAddMapping(\"doc\", map[string]interface{}{\n\t\t\t\"properties\": map[string]interface{}{\n\t\t\t\t\"user\": map[string]interface{}{\n\t\t\t\t\t\"type\": \"keyword\",\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\tdata, err := json.Marshal(svc.getBody())\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"conditions\":{\"max_age\":\"2d\",\"max_docs\":1000000},\"mappings\":{\"doc\":{\"properties\":{\"user\":{\"type\":\"keyword\"}}}},\"settings\":{\"index.number_of_shards\":2}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "indices_segments.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesSegmentsService provides low level segments information that a\n// Lucene index (shard level) is built with. Allows to be used to provide\n// more information on the state of a shard and an index, possibly\n// optimization information, data \"wasted\" on deletes, and so on.\n//\n// Find further documentation at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-segments.html.\ntype IndicesSegmentsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex              []string\n\tallowNoIndices     *bool\n\texpandWildcards    string\n\tignoreUnavailable  *bool\n\toperationThreading interface{}\n\tverbose            *bool\n}\n\n// NewIndicesSegmentsService creates a new IndicesSegmentsService.\nfunc NewIndicesSegmentsService(client *Client) *IndicesSegmentsService {\n\treturn &IndicesSegmentsService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesSegmentsService) Pretty(pretty bool) *IndicesSegmentsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesSegmentsService) Human(human bool) *IndicesSegmentsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesSegmentsService) ErrorTrace(errorTrace bool) *IndicesSegmentsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesSegmentsService) FilterPath(filterPath ...string) *IndicesSegmentsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesSegmentsService) Header(name string, value string) *IndicesSegmentsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesSegmentsService) Headers(headers http.Header) *IndicesSegmentsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a comma-separated list of index names; use `_all` or empty string\n// to perform the operation on all indices.\nfunc (s *IndicesSegmentsService) Index(indices ...string) *IndicesSegmentsService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices expression\n// resolves into no concrete indices. (This includes `_all` string or when\n// no indices have been specified).\nfunc (s *IndicesSegmentsService) AllowNoIndices(allowNoIndices bool) *IndicesSegmentsService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to concrete indices\n// that are open, closed or both.\nfunc (s *IndicesSegmentsService) ExpandWildcards(expandWildcards string) *IndicesSegmentsService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesSegmentsService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesSegmentsService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// OperationThreading is undocumented in Elasticsearch as of now.\nfunc (s *IndicesSegmentsService) OperationThreading(operationThreading interface{}) *IndicesSegmentsService {\n\ts.operationThreading = operationThreading\n\treturn s\n}\n\n// Verbose, when set to true, includes detailed memory usage by Lucene.\nfunc (s *IndicesSegmentsService) Verbose(verbose bool) *IndicesSegmentsService {\n\ts.verbose = &verbose\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesSegmentsService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\tif len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_segments\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_segments\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.operationThreading != nil {\n\t\tparams.Set(\"operation_threading\", fmt.Sprintf(\"%v\", s.operationThreading))\n\t}\n\tif s.verbose != nil {\n\t\tparams.Set(\"verbose\", fmt.Sprintf(\"%v\", *s.verbose))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesSegmentsService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesSegmentsService) Do(ctx context.Context) (*IndicesSegmentsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesSegmentsResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesSegmentsResponse is the response of IndicesSegmentsService.Do.\ntype IndicesSegmentsResponse struct {\n\t// Shards provides information returned from shards.\n\tShards *ShardsInfo `json:\"_shards\"`\n\n\t// Indices provides a map into the stats of an index.\n\t// The key of the map is the index name.\n\tIndices map[string]*IndexSegments `json:\"indices,omitempty\"`\n}\n\ntype IndexSegments struct {\n\t// Shards provides a map into the shard related information of an index.\n\t// The key of the map is the number of a specific shard.\n\tShards map[string][]*IndexSegmentsShards `json:\"shards,omitempty\"`\n}\n\ntype IndexSegmentsShards struct {\n\tRouting              *IndexSegmentsRouting `json:\"routing,omitempty\"`\n\tNumCommittedSegments int64                 `json:\"num_committed_segments,omitempty\"`\n\tNumSearchSegments    int64                 `json:\"num_search_segments\"`\n\n\t// Segments provides a map into the segment related information of a shard.\n\t// The key of the map is the specific lucene segment id.\n\tSegments map[string]*IndexSegmentsDetails `json:\"segments,omitempty\"`\n}\n\ntype IndexSegmentsRouting struct {\n\tState          string `json:\"state,omitempty\"`\n\tPrimary        bool   `json:\"primary,omitempty\"`\n\tNode           string `json:\"node,omitempty\"`\n\tRelocatingNode string `json:\"relocating_node,omitempty\"`\n}\n\ntype IndexSegmentsDetails struct {\n\tGeneration    int64                   `json:\"generation,omitempty\"`\n\tNumDocs       int64                   `json:\"num_docs,omitempty\"`\n\tDeletedDocs   int64                   `json:\"deleted_docs,omitempty\"`\n\tSize          string                  `json:\"size,omitempty\"`\n\tSizeInBytes   int64                   `json:\"size_in_bytes,omitempty\"`\n\tMemory        string                  `json:\"memory,omitempty\"`\n\tMemoryInBytes int64                   `json:\"memory_in_bytes,omitempty\"`\n\tCommitted     bool                    `json:\"committed,omitempty\"`\n\tSearch        bool                    `json:\"search,omitempty\"`\n\tVersion       string                  `json:\"version,omitempty\"`\n\tCompound      bool                    `json:\"compound,omitempty\"`\n\tMergeId       string                  `json:\"merge_id,omitempty\"`\n\tSort          []*IndexSegmentsSort    `json:\"sort,omitempty\"`\n\tRAMTree       []*IndexSegmentsRamTree `json:\"ram_tree,omitempty\"`\n\tAttributes    map[string]string       `json:\"attributes,omitempty\"`\n}\n\ntype IndexSegmentsSort struct {\n\tField   string      `json:\"field,omitempty\"`\n\tMode    string      `json:\"mode,omitempty\"`\n\tMissing interface{} `json:\"missing,omitempty\"`\n\tReverse bool        `json:\"reverse,omitempty\"`\n}\n\ntype IndexSegmentsRamTree struct {\n\tDescription string                  `json:\"description,omitempty\"`\n\tSize        string                  `json:\"size,omitempty\"`\n\tSizeInBytes int64                   `json:\"size_in_bytes,omitempty\"`\n\tChildren    []*IndexSegmentsRamTree `json:\"children,omitempty\"`\n}\n"
  },
  {
    "path": "indices_segments_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndicesSegments(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t\"/_segments\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t\"/index1/_segments\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t\"/index1%2Cindex2/_segments\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.IndexSegments().Index(test.Indices...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndexSegments(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tsegments, err := client.IndexSegments(testIndexName).Pretty(true).Human(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif segments == nil {\n\t\tt.Fatalf(\"expected response; got: %v\", segments)\n\t}\n\tindices, found := segments.Indices[testIndexName]\n\tif !found {\n\t\tt.Fatalf(\"expected index information about index %v; got: %v\", testIndexName, found)\n\t}\n\tshards, found := indices.Shards[\"0\"]\n\tif !found {\n\t\tt.Fatalf(\"expected shard information about index %v\", testIndexName)\n\t}\n\tif shards == nil {\n\t\tt.Fatalf(\"expected shard information to be != nil for index %v\", testIndexName)\n\t}\n\tshard := shards[0]\n\tif shard == nil {\n\t\tt.Fatalf(\"expected shard information to be != nil for shard 0 in index %v\", testIndexName)\n\t}\n\tif shard.Routing == nil {\n\t\tt.Fatalf(\"expected shard routing information to be != nil for index %v\", testIndexName)\n\t}\n\tsegmentDetail, found := shard.Segments[\"_0\"]\n\tif !found {\n\t\tt.Fatalf(\"expected segment detail to be != nil for index %v\", testIndexName)\n\t}\n\tif segmentDetail == nil {\n\t\tt.Fatalf(\"expected segment detail to be != nil for index %v\", testIndexName)\n\t}\n\tif segmentDetail.NumDocs == 0 {\n\t\tt.Fatal(\"expected segment to contain >= 1 docs\")\n\t}\n\tif len(segmentDetail.Attributes) == 0 {\n\t\tt.Fatalf(\"expected segment attributes map to contain at least one key, value pair for index %v\", testIndexName)\n\t}\n}\n"
  },
  {
    "path": "indices_shrink.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesShrinkService allows you to shrink an existing index into a\n// new index with fewer primary shards.\n//\n// For further details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-shrink-index.html.\ntype IndicesShrinkService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tsource              string\n\ttarget              string\n\tmasterTimeout       string\n\ttimeout             string\n\twaitForActiveShards string\n\tbodyJson            interface{}\n\tbodyString          string\n}\n\n// NewIndicesShrinkService creates a new IndicesShrinkService.\nfunc NewIndicesShrinkService(client *Client) *IndicesShrinkService {\n\treturn &IndicesShrinkService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesShrinkService) Pretty(pretty bool) *IndicesShrinkService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesShrinkService) Human(human bool) *IndicesShrinkService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesShrinkService) ErrorTrace(errorTrace bool) *IndicesShrinkService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesShrinkService) FilterPath(filterPath ...string) *IndicesShrinkService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesShrinkService) Header(name string, value string) *IndicesShrinkService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesShrinkService) Headers(headers http.Header) *IndicesShrinkService {\n\ts.headers = headers\n\treturn s\n}\n\n// Source is the name of the source index to shrink.\nfunc (s *IndicesShrinkService) Source(source string) *IndicesShrinkService {\n\ts.source = source\n\treturn s\n}\n\n// Target is the name of the target index to shrink into.\nfunc (s *IndicesShrinkService) Target(target string) *IndicesShrinkService {\n\ts.target = target\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *IndicesShrinkService) MasterTimeout(masterTimeout string) *IndicesShrinkService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *IndicesShrinkService) Timeout(timeout string) *IndicesShrinkService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// WaitForActiveShards sets the number of active shards to wait for on\n// the shrunken index before the operation returns.\nfunc (s *IndicesShrinkService) WaitForActiveShards(waitForActiveShards string) *IndicesShrinkService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// BodyJson is the configuration for the target index (`settings` and `aliases`)\n// defined as a JSON-serializable instance to be sent as the request body.\nfunc (s *IndicesShrinkService) BodyJson(body interface{}) *IndicesShrinkService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the configuration for the target index (`settings` and `aliases`)\n// defined as a string to send as the request body.\nfunc (s *IndicesShrinkService) BodyString(body string) *IndicesShrinkService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesShrinkService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{source}/_shrink/{target}\", map[string]string{\n\t\t\"source\": s.source,\n\t\t\"target\": s.target,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesShrinkService) Validate() error {\n\tvar invalid []string\n\tif s.source == \"\" {\n\t\tinvalid = append(invalid, \"Source\")\n\t}\n\tif s.target == \"\" {\n\t\tinvalid = append(invalid, \"Target\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesShrinkService) Do(ctx context.Context) (*IndicesShrinkResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else if s.bodyString != \"\" {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesShrinkResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesShrinkResponse is the response of IndicesShrinkService.Do.\ntype IndicesShrinkResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "indices_shrink_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestIndicesShrinkBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tSource   string\n\t\tTarget   string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"my_source_index\",\n\t\t\t\"my_target_index\",\n\t\t\t\"/my_source_index/_shrink/my_target_index\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.ShrinkIndex(test.Source, test.Target).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "indices_stats.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesStatsService provides stats on various metrics of one or more\n// indices. See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/indices-stats.html.\ntype IndicesStatsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tmetric           []string\n\tindex            []string\n\tlevel            string\n\ttypes            []string\n\tcompletionFields []string\n\tfielddataFields  []string\n\tfields           []string\n\tgroups           []string\n}\n\n// NewIndicesStatsService creates a new IndicesStatsService.\nfunc NewIndicesStatsService(client *Client) *IndicesStatsService {\n\treturn &IndicesStatsService{\n\t\tclient:           client,\n\t\tindex:            make([]string, 0),\n\t\tmetric:           make([]string, 0),\n\t\tcompletionFields: make([]string, 0),\n\t\tfielddataFields:  make([]string, 0),\n\t\tfields:           make([]string, 0),\n\t\tgroups:           make([]string, 0),\n\t\ttypes:            make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesStatsService) Pretty(pretty bool) *IndicesStatsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesStatsService) Human(human bool) *IndicesStatsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesStatsService) ErrorTrace(errorTrace bool) *IndicesStatsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesStatsService) FilterPath(filterPath ...string) *IndicesStatsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesStatsService) Header(name string, value string) *IndicesStatsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesStatsService) Headers(headers http.Header) *IndicesStatsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Metric limits the information returned the specific metrics. Options are:\n// docs, store, indexing, get, search, completion, fielddata, flush, merge,\n// query_cache, refresh, suggest, and warmer.\nfunc (s *IndicesStatsService) Metric(metric ...string) *IndicesStatsService {\n\ts.metric = append(s.metric, metric...)\n\treturn s\n}\n\n// Index is the list of index names; use `_all` or empty string to perform\n// the operation on all indices.\nfunc (s *IndicesStatsService) Index(indices ...string) *IndicesStatsService {\n\ts.index = append(s.index, indices...)\n\treturn s\n}\n\n// Type is a list of document types for the `indexing` index metric.\nfunc (s *IndicesStatsService) Type(types ...string) *IndicesStatsService {\n\ts.types = append(s.types, types...)\n\treturn s\n}\n\n// Level returns stats aggregated at cluster, index or shard level.\nfunc (s *IndicesStatsService) Level(level string) *IndicesStatsService {\n\ts.level = level\n\treturn s\n}\n\n// CompletionFields is a list of fields for `fielddata` and `suggest`\n// index metric (supports wildcards).\nfunc (s *IndicesStatsService) CompletionFields(completionFields ...string) *IndicesStatsService {\n\ts.completionFields = append(s.completionFields, completionFields...)\n\treturn s\n}\n\n// FielddataFields is a list of fields for `fielddata` index metric (supports wildcards).\nfunc (s *IndicesStatsService) FielddataFields(fielddataFields ...string) *IndicesStatsService {\n\ts.fielddataFields = append(s.fielddataFields, fielddataFields...)\n\treturn s\n}\n\n// Fields is a list of fields for `fielddata` and `completion` index metric\n// (supports wildcards).\nfunc (s *IndicesStatsService) Fields(fields ...string) *IndicesStatsService {\n\ts.fields = append(s.fields, fields...)\n\treturn s\n}\n\n// Groups is a list of search groups for `search` index metric.\nfunc (s *IndicesStatsService) Groups(groups ...string) *IndicesStatsService {\n\ts.groups = append(s.groups, groups...)\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesStatsService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\tif len(s.index) > 0 && len(s.metric) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_stats/{metric}\", map[string]string{\n\t\t\t\"index\":  strings.Join(s.index, \",\"),\n\t\t\t\"metric\": strings.Join(s.metric, \",\"),\n\t\t})\n\t} else if len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_stats\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else if len(s.metric) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_stats/{metric}\", map[string]string{\n\t\t\t\"metric\": strings.Join(s.metric, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_stats\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif len(s.groups) > 0 {\n\t\tparams.Set(\"groups\", strings.Join(s.groups, \",\"))\n\t}\n\tif s.level != \"\" {\n\t\tparams.Set(\"level\", s.level)\n\t}\n\tif len(s.types) > 0 {\n\t\tparams.Set(\"types\", strings.Join(s.types, \",\"))\n\t}\n\tif len(s.completionFields) > 0 {\n\t\tparams.Set(\"completion_fields\", strings.Join(s.completionFields, \",\"))\n\t}\n\tif len(s.fielddataFields) > 0 {\n\t\tparams.Set(\"fielddata_fields\", strings.Join(s.fielddataFields, \",\"))\n\t}\n\tif len(s.fields) > 0 {\n\t\tparams.Set(\"fields\", strings.Join(s.fields, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesStatsService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IndicesStatsService) Do(ctx context.Context) (*IndicesStatsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesStatsResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesStatsResponse is the response of IndicesStatsService.Do.\ntype IndicesStatsResponse struct {\n\t// Shards provides information returned from shards.\n\tShards *ShardsInfo `json:\"_shards\"`\n\n\t// All provides summary stats about all indices.\n\tAll *IndexStats `json:\"_all,omitempty\"`\n\n\t// Indices provides a map into the stats of an index. The key of the\n\t// map is the index name.\n\tIndices map[string]*IndexStats `json:\"indices,omitempty\"`\n}\n\n// IndexStats is index stats for a specific index.\ntype IndexStats struct {\n\tUUID      string                          `json:\"uuid,omitempty\"`\n\tPrimaries *IndexStatsDetails              `json:\"primaries,omitempty\"`\n\tTotal     *IndexStatsDetails              `json:\"total,omitempty\"`\n\tShards    map[string][]*IndexStatsDetails `json:\"shards,omitempty\"`\n}\n\ntype IndexStatsDetails struct {\n\tRouting         *IndexStatsRouting         `json:\"routing,omitempty\"`\n\tDocs            *IndexStatsDocs            `json:\"docs,omitempty\"`\n\tStore           *IndexStatsStore           `json:\"store,omitempty\"`\n\tIndexing        *IndexStatsIndexing        `json:\"indexing,omitempty\"`\n\tGet             *IndexStatsGet             `json:\"get,omitempty\"`\n\tSearch          *IndexStatsSearch          `json:\"search,omitempty\"`\n\tMerges          *IndexStatsMerges          `json:\"merges,omitempty\"`\n\tRefresh         *IndexStatsRefresh         `json:\"refresh,omitempty\"`\n\tRecovery        *IndexStatsRecovery        `json:\"recovery,omitempty\"`\n\tFlush           *IndexStatsFlush           `json:\"flush,omitempty\"`\n\tWarmer          *IndexStatsWarmer          `json:\"warmer,omitempty\"`\n\tFilterCache     *IndexStatsFilterCache     `json:\"filter_cache,omitempty\"`\n\tIdCache         *IndexStatsIdCache         `json:\"id_cache,omitempty\"`\n\tFielddata       *IndexStatsFielddata       `json:\"fielddata,omitempty\"`\n\tPercolate       *IndexStatsPercolate       `json:\"percolate,omitempty\"`\n\tCompletion      *IndexStatsCompletion      `json:\"completion,omitempty\"`\n\tSegments        *IndexStatsSegments        `json:\"segments,omitempty\"`\n\tTranslog        *IndexStatsTranslog        `json:\"translog,omitempty\"`\n\tSuggest         *IndexStatsSuggest         `json:\"suggest,omitempty\"`\n\tQueryCache      *IndexStatsQueryCache      `json:\"query_cache,omitempty\"`\n\tRequestCache    *IndexStatsRequestCache    `json:\"request_cache,omitempty\"`\n\tCommit          *IndexStatsCommit          `json:\"commit,omitempty\"`\n\tSeqNo           *IndexStatsSeqNo           `json:\"seq_no,omitempty\"`\n\tRetentionLeases *IndexStatsRetentionLeases `json:\"retention_leases,omitempty\"`\n\tShardPath       *IndexStatsShardPath       `json:\"shard_path,omitempty\"`\n\tShardStats      *IndexStatsShardStats      `json:\"shard_stats,omitempty\"`\n}\n\ntype IndexStatsRouting struct {\n\tState          string  `json:\"state\"` // e.g. \"STARTED\"\n\tPrimary        bool    `json:\"primary\"`\n\tNode           string  `json:\"node\"` // e.g. \"-aXnGv4oTW6bIIl0db3eCg\"\n\tRelocatingNode *string `json:\"relocating_node\"`\n}\n\ntype IndexStatsShardPath struct {\n\tStatePath        string `json:\"state_path\"` // e.g. \"/usr/share/elasticsearch/data/nodes/0\"\n\tDataPath         string `json:\"data_path\"`  // e.g. \"/usr/share/elasticsearch/data/nodes/0\"\n\tIsCustomDataPath bool   `json:\"is_custom_data_path\"`\n}\n\ntype IndexStatsShardStats struct {\n\tTotalCount int64 `json:\"total_count,omitempty\"`\n}\n\ntype IndexStatsDocs struct {\n\tCount   int64 `json:\"count,omitempty\"`\n\tDeleted int64 `json:\"deleted,omitempty\"`\n}\n\ntype IndexStatsStore struct {\n\tSize                    string `json:\"size,omitempty\"` // human size, e.g. 119.3mb\n\tSizeInBytes             int64  `json:\"size_in_bytes,omitempty\"`\n\tTotalDataSetSize        string `json:\"total_data_set_size,omitempty\"`\n\tTotalDataSetSizeInBytes int64  `json:\"total_data_set_size_in_bytes,omitempty\"`\n\tReserved                string `json:\"reserved,omitempty\"`\n\tReservedInBytes         int64  `json:\"reserved_in_bytes,omitempty\"`\n}\n\ntype IndexStatsIndexing struct {\n\tIndexTotal           int64  `json:\"index_total,omitempty\"`\n\tIndexTime            string `json:\"index_time,omitempty\"`\n\tIndexTimeInMillis    int64  `json:\"index_time_in_millis,omitempty\"`\n\tIndexCurrent         int64  `json:\"index_current,omitempty\"`\n\tIndexFailed          int64  `json:\"index_failed,omitempty\"`\n\tDeleteTotal          int64  `json:\"delete_total,omitempty\"`\n\tDeleteTime           string `json:\"delete_time,omitempty\"`\n\tDeleteTimeInMillis   int64  `json:\"delete_time_in_millis,omitempty\"`\n\tDeleteCurrent        int64  `json:\"delete_current,omitempty\"`\n\tNoopUpdateTotal      int64  `json:\"noop_update_total,omitempty\"`\n\tIsThrottled          bool   `json:\"is_throttled,omitempty\"`\n\tThrottleTime         string `json:\"throttle_time,omitempty\"`\n\tThrottleTimeInMillis int64  `json:\"throttle_time_in_millis,omitempty\"`\n}\n\ntype IndexStatsGet struct {\n\tTotal               int64  `json:\"total,omitempty\"`\n\tGetTime             string `json:\"getTime,omitempty\"` // 7.4.0 uses \"getTime\", earlier versions used \"get_time\"\n\tTimeInMillis        int64  `json:\"time_in_millis,omitempty\"`\n\tExistsTotal         int64  `json:\"exists_total,omitempty\"`\n\tExistsTime          string `json:\"exists_time,omitempty\"`\n\tExistsTimeInMillis  int64  `json:\"exists_time_in_millis,omitempty\"`\n\tMissingTotal        int64  `json:\"missing_total,omitempty\"`\n\tMissingTime         string `json:\"missing_time,omitempty\"`\n\tMissingTimeInMillis int64  `json:\"missing_time_in_millis,omitempty\"`\n\tCurrent             int64  `json:\"current,omitempty\"`\n}\n\ntype IndexStatsSearch struct {\n\tOpenContexts        int64  `json:\"open_contexts,omitempty\"`\n\tQueryTotal          int64  `json:\"query_total,omitempty\"`\n\tQueryTime           string `json:\"query_time,omitempty\"`\n\tQueryTimeInMillis   int64  `json:\"query_time_in_millis,omitempty\"`\n\tQueryCurrent        int64  `json:\"query_current,omitempty\"`\n\tFetchTotal          int64  `json:\"fetch_total,omitempty\"`\n\tFetchTime           string `json:\"fetch_time,omitempty\"`\n\tFetchTimeInMillis   int64  `json:\"fetch_time_in_millis,omitempty\"`\n\tFetchCurrent        int64  `json:\"fetch_current,omitempty\"`\n\tScrollTotal         int64  `json:\"scroll_total,omitempty\"`\n\tScrollTime          string `json:\"scroll_time,omitempty\"`\n\tScrollTimeInMillis  int64  `json:\"scroll_time_in_millis,omitempty\"`\n\tScrollCurrent       int64  `json:\"scroll_current,omitempty\"`\n\tSuggestTotal        int64  `json:\"suggest_total,omitempty\"`\n\tSuggestTime         string `json:\"suggest_time,omitempty\"`\n\tSuggestTimeInMillis int64  `json:\"suggest_time_in_millis,omitempty\"`\n\tSuggestCurrent      int64  `json:\"suggest_current,omitempty\"`\n}\n\ntype IndexStatsMerges struct {\n\tCurrent                    int64  `json:\"current,omitempty\"`\n\tCurrentDocs                int64  `json:\"current_docs,omitempty\"`\n\tCurrentSize                string `json:\"current_size,omitempty\"`\n\tCurrentSizeInBytes         int64  `json:\"current_size_in_bytes,omitempty\"`\n\tTotal                      int64  `json:\"total,omitempty\"`\n\tTotalTime                  string `json:\"total_time,omitempty\"`\n\tTotalTimeInMillis          int64  `json:\"total_time_in_millis,omitempty\"`\n\tTotalDocs                  int64  `json:\"total_docs,omitempty\"`\n\tTotalSize                  string `json:\"total_size,omitempty\"`\n\tTotalSizeInBytes           int64  `json:\"total_size_in_bytes,omitempty\"`\n\tTotalStoppedTime           string `json:\"total_stopped_time,omitempty\"`\n\tTotalStoppedTimeInMillis   int64  `json:\"total_stopped_time_in_millis,omitempty\"`\n\tTotalThrottledTime         string `json:\"total_throttled_time,omitempty\"`\n\tTotalThrottledTimeInMillis int64  `json:\"total_throttled_time_in_millis,omitempty\"`\n\tTotalAutoThrottle          string `json:\"total_auto_throttle,omitempty\"`\n\tTotalAutoThrottleInBytes   int64  `json:\"total_auto_throttle_in_bytes,omitempty\"`\n}\n\ntype IndexStatsRefresh struct {\n\tTotal                     int64  `json:\"total,omitempty\"`\n\tTotalTime                 string `json:\"total_time,omitempty\"`\n\tTotalTimeInMillis         int64  `json:\"total_time_in_millis,omitempty\"`\n\tExternalTotal             int64  `json:\"external_total,omitempty\"`\n\tExternalTotalTime         string `json:\"external_total_time,omitempty\"`\n\tExternalTotalTimeInMillis int64  `json:\"external_total_time_in_millis,omitempty\"`\n\tListeners                 int64  `json:\"listeners,omitempty\"`\n}\n\ntype IndexStatsRecovery struct {\n\tCurrentAsSource      int64  `json:\"current_as_source,omitempty\"`\n\tCurrentAsTarget      int64  `json:\"current_as_target,omitempty\"`\n\tThrottleTime         string `json:\"throttle_time,omitempty\"`\n\tThrottleTimeInMillis int64  `json:\"throttle_time_in_millis,omitempty\"`\n}\n\ntype IndexStatsFlush struct {\n\tTotal             int64  `json:\"total,omitempty\"`\n\tTotalTime         string `json:\"total_time,omitempty\"`\n\tTotalTimeInMillis int64  `json:\"total_time_in_millis,omitempty\"`\n\tPeriodic          int64  `json:\"periodic,omitempty\"`\n}\n\ntype IndexStatsWarmer struct {\n\tCurrent           int64  `json:\"current,omitempty\"`\n\tTotal             int64  `json:\"total,omitempty\"`\n\tTotalTime         string `json:\"total_time,omitempty\"`\n\tTotalTimeInMillis int64  `json:\"total_time_in_millis,omitempty\"`\n}\n\ntype IndexStatsRequestCache struct {\n\tMemorySize        string `json:\"memory_size,omitempty\"`\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes,omitempty\"`\n\tEvictions         int64  `json:\"evictions,omitempty\"`\n\tHitCount          int64  `json:\"hit_count,omitempty\"`\n\tMissCount         int64  `json:\"miss_count,omitempty\"`\n}\n\ntype IndexStatsCommit struct {\n\tID         string            `json:\"id,omitempty\"` // lucene commit ID in base64, e.g. \"m2tDMYHzSpSV6zJH0lIAnA==\"\n\tGeneration int64             `json:\"generation,omitempty\"`\n\tUserData   map[string]string `json:\"user_data,omitempty\"`\n\tNumDocs    int64             `json:\"num_docs,omitempty\"`\n}\n\ntype IndexStatsFilterCache struct {\n\tMemorySize        string `json:\"memory_size,omitempty\"`\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes,omitempty\"`\n\tEvictions         int64  `json:\"evictions,omitempty\"`\n}\n\ntype IndexStatsIdCache struct {\n\tMemorySize        string `json:\"memory_size,omitempty\"`\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes,omitempty\"`\n}\n\ntype IndexStatsFielddata struct {\n\tMemorySize        string `json:\"memory_size,omitempty\"`\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes,omitempty\"`\n\tEvictions         int64  `json:\"evictions,omitempty\"`\n}\n\ntype IndexStatsPercolate struct {\n\tTotal             int64  `json:\"total,omitempty\"`\n\tGetTime           string `json:\"get_time,omitempty\"`\n\tTimeInMillis      int64  `json:\"time_in_millis,omitempty\"`\n\tCurrent           int64  `json:\"current,omitempty\"`\n\tMemorySize        string `json:\"memory_size,omitempty\"`\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes,omitempty\"`\n\tQueries           int64  `json:\"queries,omitempty\"`\n}\n\ntype IndexStatsCompletion struct {\n\tSize        string `json:\"size,omitempty\"`\n\tSizeInBytes int64  `json:\"size_in_bytes,omitempty\"`\n}\n\ntype IndexStatsSegments struct {\n\tCount                     int64                                       `json:\"count\"`\n\tMemory                    string                                      `json:\"memory\"` // e.g. \"61.3kb\"\n\tMemoryInBytes             int64                                       `json:\"memory_in_bytes\"`\n\tTermsMemory               string                                      `json:\"terms_memory\"` // e.g. \"61.3kb\"\n\tTermsMemoryInBytes        int64                                       `json:\"terms_memory_in_bytes\"`\n\tStoredFieldsMemory        string                                      `json:\"stored_fields_memory\"` // e.g. \"61.3kb\"\n\tStoredFieldsMemoryInBytes int64                                       `json:\"stored_fields_memory_in_bytes\"`\n\tTermVectorsMemory         string                                      `json:\"term_vectors_memory\"` // e.g. \"61.3kb\"\n\tTermVectorsMemoryInBytes  int64                                       `json:\"term_vectors_memory_in_bytes\"`\n\tNormsMemory               string                                      `json:\"norms_memory\"` // e.g. \"61.3kb\"\n\tNormsMemoryInBytes        int64                                       `json:\"norms_memory_in_bytes\"`\n\tPointsMemory              string                                      `json:\"points_memory\"` // e.g. \"61.3kb\"\n\tPointsMemoryInBytes       int64                                       `json:\"points_memory_in_bytes\"`\n\tDocValuesMemory           string                                      `json:\"doc_values_memory\"` // e.g. \"61.3kb\"\n\tDocValuesMemoryInBytes    int64                                       `json:\"doc_values_memory_in_bytes\"`\n\tIndexWriterMemory         string                                      `json:\"index_writer_memory\"` // e.g. \"61.3kb\"\n\tIndexWriterMemoryInBytes  int64                                       `json:\"index_writer_memory_in_bytes\"`\n\tVersionMapMemory          string                                      `json:\"version_map_memory\"` // e.g. \"61.3kb\"\n\tVersionMapMemoryInBytes   int64                                       `json:\"version_map_memory_in_bytes\"`\n\tFixedBitSet               string                                      `json:\"fixed_bit_set\"` // e.g. \"61.3kb\"\n\tFixedBitSetInBytes        int64                                       `json:\"fixed_bit_set_memory_in_bytes\"`\n\tMaxUnsafeAutoIDTimestamp  int64                                       `json:\"max_unsafe_auto_id_timestamp\"`\n\tFileSizes                 map[string]*ClusterStatsIndicesSegmentsFile `json:\"file_sizes\"`\n}\n\ntype IndexStatsTranslog struct {\n\tOperations              int64  `json:\"operations,omitempty\"`\n\tSize                    string `json:\"size,omitempty\"`\n\tSizeInBytes             int64  `json:\"size_in_bytes,omitempty\"`\n\tUncommittedOperations   int64  `json:\"uncommitted_operations,omitempty\"`\n\tUncommittedSize         string `json:\"uncommitted_size,omitempty\"`\n\tUncommittedSizeInBytes  int64  `json:\"uncommitted_size_in_bytes,omitempty\"`\n\tEarliestLastModifiedAge int64  `json:\"earliest_last_modified_age,omitempty\"`\n}\n\ntype IndexStatsSuggest struct {\n\tTotal        int64  `json:\"total,omitempty\"`\n\tTime         string `json:\"time,omitempty\"`\n\tTimeInMillis int64  `json:\"time_in_millis,omitempty\"`\n\tCurrent      int64  `json:\"current,omitempty\"`\n}\n\ntype IndexStatsQueryCache struct {\n\tMemorySize        string `json:\"memory_size,omitempty\"`\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes,omitempty\"`\n\tTotalCount        int64  `json:\"total_count,omitempty\"`\n\tHitCount          int64  `json:\"hit_count,omitempty\"`\n\tMissCount         int64  `json:\"miss_count,omitempty\"`\n\tCacheSize         int64  `json:\"cache_size,omitempty\"`\n\tCacheCount        int64  `json:\"cache_count,omitempty\"`\n\tEvictions         int64  `json:\"evictions,omitempty\"`\n}\n\ntype IndexStatsSeqNo struct {\n\tMaxSeqNo         int64 `json:\"max_seq_no,omitempty\"`\n\tLocalCheckpoint  int64 `json:\"local_checkpoint,omitempty\"`\n\tGlobalCheckpoint int64 `json:\"global_checkpoint,omitempty\"`\n}\n\ntype IndexStatsRetentionLeases struct {\n\tPrimaryTerm int64                       `json:\"primary_term,omitempty\"`\n\tVersion     int64                       `json:\"version,omitempty\"`\n\tLeases      []*IndexStatsRetentionLease `json:\"leases,omitempty\"`\n}\n\ntype IndexStatsRetentionLease struct {\n\tId             string `json:\"id,omitempty\"`\n\tRetainingSeqNo int64  `json:\"retaining_seq_no,omitempty\"`\n\tTimestamp      int64  `json:\"timestamp,omitempty\"`\n\tSource         string `json:\"source,omitempty\"`\n}\n"
  },
  {
    "path": "indices_stats_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIndexStatsBuildURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tMetrics  []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"/_stats\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{},\n\t\t\t\"/index1/_stats\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"metric1\"},\n\t\t\t\"/_stats/metric1\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{\"metric1\"},\n\t\t\t\"/index1/_stats/metric1\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{\"metric1\"},\n\t\t\t\"/index1%2Cindex2/_stats/metric1\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{\"metric1\", \"metric2\"},\n\t\t\t\"/index1%2Cindex2/_stats/metric1%2Cmetric2\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.IndexStats().Index(test.Indices...).Metric(test.Metrics...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"case #%d: %v\", i+1, err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIndexStats(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tstats, err := client.IndexStats(testIndexName).Human(true).Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif stats == nil {\n\t\tt.Fatalf(\"expected response; got: %v\", stats)\n\t}\n\tstat, found := stats.Indices[testIndexName]\n\tif !found {\n\t\tt.Fatalf(\"expected stats about index %q; got: %v\", testIndexName, found)\n\t}\n\tif stat.Total == nil {\n\t\tt.Fatalf(\"expected total to be != nil; got: %v\", stat.Total)\n\t}\n\tif stat.Total.Docs == nil {\n\t\tt.Fatalf(\"expected total docs to be != nil; got: %v\", stat.Total.Docs)\n\t}\n\tif stat.Total.Docs.Count == 0 {\n\t\tt.Fatalf(\"expected total docs count to be > 0; got: %d\", stat.Total.Docs.Count)\n\t}\n}\n\nfunc TestIndexStatsWithShards(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tstats, err := client.IndexStats(testIndexName).Level(\"shards\").Human(true).Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t}\n\tif stats == nil {\n\t\tt.Fatalf(\"expected response; got: %v\", stats)\n\t}\n\tstat, found := stats.Indices[testIndexName]\n\tif !found {\n\t\tt.Fatalf(\"expected stats about index %q; got: %v\", testIndexName, found)\n\t}\n\tif stat.Total == nil {\n\t\tt.Fatalf(\"expected total to be != nil; got: %v\", stat.Total)\n\t}\n\tif stat.Total.Docs == nil {\n\t\tt.Fatalf(\"expected total docs to be != nil; got: %v\", stat.Total.Docs)\n\t}\n\tif stat.Total.Docs.Count == 0 {\n\t\tt.Fatalf(\"expected total docs count to be > 0; got: %d\", stat.Total.Docs.Count)\n\t}\n\tif stat.Shards == nil {\n\t\tt.Fatalf(\"expected shard level information to be != nil; got: %v\", stat.Shards)\n\t}\n\tshard, found := stat.Shards[\"0\"]\n\tif !found || shard == nil {\n\t\tt.Fatalf(\"expected shard level information for shard 0; got: %v (found=%v)\", shard, found)\n\t}\n\tif len(shard) != 1 {\n\t\tt.Fatalf(\"expected shard level information array to be == 1; got: %v\", len(shard))\n\t}\n\tif shard[0].Docs == nil {\n\t\tt.Fatalf(\"expected docs to be != nil; got: %v\", shard[0].Docs)\n\t}\n}\n"
  },
  {
    "path": "indices_unfreeze.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IndicesUnfreezeService unfreezes an index.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/unfreeze-index-api.html\n// and https://www.elastic.co/blog/creating-frozen-indices-with-the-elasticsearch-freeze-index-api\n// for details.\n//\n// Deprecated: Frozen indices are deprecated because they provide no benefit\n// given improvements in heap memory utilization.\ntype IndicesUnfreezeService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex               string\n\ttimeout             string\n\tmasterTimeout       string\n\tignoreUnavailable   *bool\n\tallowNoIndices      *bool\n\texpandWildcards     string\n\twaitForActiveShards string\n}\n\n// NewIndicesUnfreezeService creates a new IndicesUnfreezeService.\nfunc NewIndicesUnfreezeService(client *Client) *IndicesUnfreezeService {\n\treturn &IndicesUnfreezeService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IndicesUnfreezeService) Pretty(pretty bool) *IndicesUnfreezeService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IndicesUnfreezeService) Human(human bool) *IndicesUnfreezeService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IndicesUnfreezeService) ErrorTrace(errorTrace bool) *IndicesUnfreezeService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IndicesUnfreezeService) FilterPath(filterPath ...string) *IndicesUnfreezeService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IndicesUnfreezeService) Header(name string, value string) *IndicesUnfreezeService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IndicesUnfreezeService) Headers(headers http.Header) *IndicesUnfreezeService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the index to unfreeze.\nfunc (s *IndicesUnfreezeService) Index(index string) *IndicesUnfreezeService {\n\ts.index = index\n\treturn s\n}\n\n// Timeout allows to specify an explicit timeout.\nfunc (s *IndicesUnfreezeService) Timeout(timeout string) *IndicesUnfreezeService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout allows to specify a timeout for connection to master.\nfunc (s *IndicesUnfreezeService) MasterTimeout(masterTimeout string) *IndicesUnfreezeService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *IndicesUnfreezeService) IgnoreUnavailable(ignoreUnavailable bool) *IndicesUnfreezeService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices expression\n// resolves into no concrete indices. (This includes `_all` string or when\n// no indices have been specified).\nfunc (s *IndicesUnfreezeService) AllowNoIndices(allowNoIndices bool) *IndicesUnfreezeService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards specifies whether to expand wildcard expression to\n// concrete indices that are open, closed or both..\nfunc (s *IndicesUnfreezeService) ExpandWildcards(expandWildcards string) *IndicesUnfreezeService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// WaitForActiveShards sets the number of active shards to wait for\n// before the operation returns.\nfunc (s *IndicesUnfreezeService) WaitForActiveShards(numShards string) *IndicesUnfreezeService {\n\ts.waitForActiveShards = numShards\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IndicesUnfreezeService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/_unfreeze\", map[string]string{\n\t\t\"index\": s.index,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IndicesUnfreezeService) Validate() error {\n\tvar invalid []string\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the service.\n//\n// Deprecated: Frozen indices are deprecated because they provide no benefit\n// given improvements in heap memory utilization.\nfunc (s *IndicesUnfreezeService) Do(ctx context.Context) (*IndicesUnfreezeResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IndicesUnfreezeResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IndicesUnfreezeResponse is the outcome of freezing an index.\ntype IndicesUnfreezeResponse struct {\n\tShards *ShardsInfo `json:\"_shards\"`\n}\n"
  },
  {
    "path": "indices_unfreeze_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestIndicesUnfreezeBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndex    string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"index1\",\n\t\t\t\"/index1/_unfreeze\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.UnfreezeIndex(test.Index).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ingest_delete_pipeline.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IngestDeletePipelineService deletes pipelines by ID.\n// It is documented at https://www.elastic.co/guide/en/elasticsearch/reference/7.0/delete-pipeline-api.html.\ntype IngestDeletePipelineService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid            string\n\tmasterTimeout string\n\ttimeout       string\n}\n\n// NewIngestDeletePipelineService creates a new IngestDeletePipelineService.\nfunc NewIngestDeletePipelineService(client *Client) *IngestDeletePipelineService {\n\treturn &IngestDeletePipelineService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IngestDeletePipelineService) Pretty(pretty bool) *IngestDeletePipelineService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IngestDeletePipelineService) Human(human bool) *IngestDeletePipelineService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IngestDeletePipelineService) ErrorTrace(errorTrace bool) *IngestDeletePipelineService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IngestDeletePipelineService) FilterPath(filterPath ...string) *IngestDeletePipelineService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IngestDeletePipelineService) Header(name string, value string) *IngestDeletePipelineService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IngestDeletePipelineService) Headers(headers http.Header) *IngestDeletePipelineService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is documented as: Pipeline ID.\nfunc (s *IngestDeletePipelineService) Id(id string) *IngestDeletePipelineService {\n\ts.id = id\n\treturn s\n}\n\n// MasterTimeout is documented as: Explicit operation timeout for connection to master node.\nfunc (s *IngestDeletePipelineService) MasterTimeout(masterTimeout string) *IngestDeletePipelineService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Timeout is documented as: Explicit operation timeout.\nfunc (s *IngestDeletePipelineService) Timeout(timeout string) *IngestDeletePipelineService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IngestDeletePipelineService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_ingest/pipeline/{id}\", map[string]string{\n\t\t\"id\": s.id,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IngestDeletePipelineService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IngestDeletePipelineService) Do(ctx context.Context) (*IngestDeletePipelineResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IngestDeletePipelineResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IngestDeletePipelineResponse is the response of IngestDeletePipelineService.Do.\ntype IngestDeletePipelineResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "ingest_delete_pipeline_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestIngestDeletePipelineURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tId       string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"my-pipeline-id\",\n\t\t\t\"/_ingest/pipeline/my-pipeline-id\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.IngestDeletePipeline(test.Id).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ingest_get_pipeline.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IngestGetPipelineService returns pipelines based on ID.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/get-pipeline-api.html\n// for documentation.\ntype IngestGetPipelineService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid            []string\n\tmasterTimeout string\n}\n\n// NewIngestGetPipelineService creates a new IngestGetPipelineService.\nfunc NewIngestGetPipelineService(client *Client) *IngestGetPipelineService {\n\treturn &IngestGetPipelineService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IngestGetPipelineService) Pretty(pretty bool) *IngestGetPipelineService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IngestGetPipelineService) Human(human bool) *IngestGetPipelineService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IngestGetPipelineService) ErrorTrace(errorTrace bool) *IngestGetPipelineService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IngestGetPipelineService) FilterPath(filterPath ...string) *IngestGetPipelineService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IngestGetPipelineService) Header(name string, value string) *IngestGetPipelineService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IngestGetPipelineService) Headers(headers http.Header) *IngestGetPipelineService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is a list of pipeline ids. Wildcards supported.\nfunc (s *IngestGetPipelineService) Id(id ...string) *IngestGetPipelineService {\n\ts.id = append(s.id, id...)\n\treturn s\n}\n\n// MasterTimeout is an explicit operation timeout for connection to master node.\nfunc (s *IngestGetPipelineService) MasterTimeout(masterTimeout string) *IngestGetPipelineService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IngestGetPipelineService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\t// Build URL\n\tif len(s.id) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_ingest/pipeline/{id}\", map[string]string{\n\t\t\t\"id\": strings.Join(s.id, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_ingest/pipeline\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IngestGetPipelineService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IngestGetPipelineService) Do(ctx context.Context) (IngestGetPipelineResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret IngestGetPipelineResponse\n\tif err := json.Unmarshal(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IngestGetPipelineResponse is the response of IngestGetPipelineService.Do.\ntype IngestGetPipelineResponse map[string]*IngestGetPipeline\n\n// IngestGetPipeline describes a specific ingest pipeline, its\n// processors etc.\ntype IngestGetPipeline struct {\n\tDescription string                   `json:\"description\"`\n\tProcessors  []map[string]interface{} `json:\"processors\"`\n\tVersion     int64                    `json:\"version,omitempty\"`\n\tOnFailure   []map[string]interface{} `json:\"on_failure,omitempty\"`\n}\n"
  },
  {
    "path": "ingest_get_pipeline_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestIngestGetPipelineURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tId       []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\tnil,\n\t\t\t\"/_ingest/pipeline\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"my-pipeline-id\"},\n\t\t\t\"/_ingest/pipeline/my-pipeline-id\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"*\"},\n\t\t\t\"/_ingest/pipeline/%2A\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"pipeline-1\", \"pipeline-2\"},\n\t\t\t\"/_ingest/pipeline/pipeline-1%2Cpipeline-2\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.IngestGetPipeline(test.Id...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestIngestLifecycle(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// With the new ES Docker images, XPack is already installed and returns a pipeline. So we cannot test for \"no pipelines\". Skipping for now.\n\t/*\n\t\t// Get all pipelines (returns 404 that indicates an error)\n\t\tgetres, err := client.IngestGetPipeline().Do(context.TODO())\n\t\tif err == nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif getres != nil {\n\t\t\tt.Fatalf(\"expected no response, got %v\", getres)\n\t\t}\n\t//*/\n\n\t// Add a pipeline\n\tpipelineDef := `{\n  \"description\" : \"reset retweets\",\n  \"processors\" : [\n    {\n      \"set\" : {\n        \"field\": \"retweets\",\n        \"value\": 0\n      }\n    }\n  ]\n}`\n\tputres, err := client.IngestPutPipeline(\"my-pipeline\").BodyString(pipelineDef).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif putres == nil {\n\t\tt.Fatal(\"expected response, got nil\")\n\t}\n\tif want, have := true, putres.Acknowledged; want != have {\n\t\tt.Fatalf(\"expected ack = %v, got %v\", want, have)\n\t}\n\n\t// Get all pipelines again\n\t{\n\t\tgetres, err := client.IngestGetPipeline().Do(context.TODO())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif have := len(getres); have == 0 {\n\t\t\tt.Fatalf(\"expected at least 1 pipeline, got %d\", have)\n\t\t}\n\t\tpipeline, found := getres[\"my-pipeline\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected to find pipline with id %q\", \"my-pipeline\")\n\t\t}\n\t\tif want, have := \"reset retweets\", pipeline.Description; want != have {\n\t\t\tt.Fatalf(\"expected pipeline description of %q, have %q\", want, have)\n\t\t}\n\t}\n\n\t// Get pipeline by ID\n\t{\n\t\tgetres, err := client.IngestGetPipeline(\"my-pipeline\").Do(context.TODO())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif want, have := 1, len(getres); want != have {\n\t\t\tt.Fatalf(\"expected %d pipelines, got %d\", want, have)\n\t\t}\n\t\tif _, found := getres[\"my-pipeline\"]; !found {\n\t\t\tt.Fatalf(\"expected to find pipline with id %q\", \"my-pipeline\")\n\t\t}\n\t}\n\n\t// Delete pipeline\n\tdelres, err := client.IngestDeletePipeline(\"my-pipeline\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif delres == nil {\n\t\tt.Fatal(\"expected response, got nil\")\n\t}\n\tif want, have := true, delres.Acknowledged; want != have {\n\t\tt.Fatalf(\"expected ack = %v, got %v\", want, have)\n\t}\n}\n"
  },
  {
    "path": "ingest_put_pipeline.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IngestPutPipelineService adds pipelines and updates existing pipelines in\n// the cluster.\n//\n// It is documented at https://www.elastic.co/guide/en/elasticsearch/reference/7.0/put-pipeline-api.html.\ntype IngestPutPipelineService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid            string\n\tmasterTimeout string\n\ttimeout       string\n\tbodyJson      interface{}\n\tbodyString    string\n}\n\n// NewIngestPutPipelineService creates a new IngestPutPipelineService.\nfunc NewIngestPutPipelineService(client *Client) *IngestPutPipelineService {\n\treturn &IngestPutPipelineService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IngestPutPipelineService) Pretty(pretty bool) *IngestPutPipelineService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IngestPutPipelineService) Human(human bool) *IngestPutPipelineService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IngestPutPipelineService) ErrorTrace(errorTrace bool) *IngestPutPipelineService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IngestPutPipelineService) FilterPath(filterPath ...string) *IngestPutPipelineService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IngestPutPipelineService) Header(name string, value string) *IngestPutPipelineService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IngestPutPipelineService) Headers(headers http.Header) *IngestPutPipelineService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is the pipeline ID.\nfunc (s *IngestPutPipelineService) Id(id string) *IngestPutPipelineService {\n\ts.id = id\n\treturn s\n}\n\n// MasterTimeout is an explicit operation timeout for connection to master node.\nfunc (s *IngestPutPipelineService) MasterTimeout(masterTimeout string) *IngestPutPipelineService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Timeout specifies an explicit operation timeout.\nfunc (s *IngestPutPipelineService) Timeout(timeout string) *IngestPutPipelineService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// BodyJson is the ingest definition, defined as a JSON-serializable document.\n// Use e.g. a map[string]interface{} here.\nfunc (s *IngestPutPipelineService) BodyJson(body interface{}) *IngestPutPipelineService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the ingest definition, specified as a string.\nfunc (s *IngestPutPipelineService) BodyString(body string) *IngestPutPipelineService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IngestPutPipelineService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_ingest/pipeline/{id}\", map[string]string{\n\t\t\"id\": s.id,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IngestPutPipelineService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif s.bodyString == \"\" && s.bodyJson == nil {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IngestPutPipelineService) Do(ctx context.Context) (*IngestPutPipelineResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IngestPutPipelineResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IngestPutPipelineResponse is the response of IngestPutPipelineService.Do.\ntype IngestPutPipelineResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "ingest_put_pipeline_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestIngestPutPipelineURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tId       string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"my-pipeline-id\",\n\t\t\t\"/_ingest/pipeline/my-pipeline-id\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.IngestPutPipeline(test.Id).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ingest_simulate_pipeline.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// IngestSimulatePipelineService executes a specific pipeline against the set of\n// documents provided in the body of the request.\n//\n// The API is documented at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/simulate-pipeline-api.html.\ntype IngestSimulatePipelineService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid         string\n\tverbose    *bool\n\tbodyJson   interface{}\n\tbodyString string\n}\n\n// NewIngestSimulatePipelineService creates a new IngestSimulatePipeline.\nfunc NewIngestSimulatePipelineService(client *Client) *IngestSimulatePipelineService {\n\treturn &IngestSimulatePipelineService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *IngestSimulatePipelineService) Pretty(pretty bool) *IngestSimulatePipelineService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *IngestSimulatePipelineService) Human(human bool) *IngestSimulatePipelineService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *IngestSimulatePipelineService) ErrorTrace(errorTrace bool) *IngestSimulatePipelineService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *IngestSimulatePipelineService) FilterPath(filterPath ...string) *IngestSimulatePipelineService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *IngestSimulatePipelineService) Header(name string, value string) *IngestSimulatePipelineService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *IngestSimulatePipelineService) Headers(headers http.Header) *IngestSimulatePipelineService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id specifies the pipeline ID.\nfunc (s *IngestSimulatePipelineService) Id(id string) *IngestSimulatePipelineService {\n\ts.id = id\n\treturn s\n}\n\n// Verbose mode. Display data output for each processor in executed pipeline.\nfunc (s *IngestSimulatePipelineService) Verbose(verbose bool) *IngestSimulatePipelineService {\n\ts.verbose = &verbose\n\treturn s\n}\n\n// BodyJson is the ingest definition, defined as a JSON-serializable simulate\n// definition. Use e.g. a map[string]interface{} here.\nfunc (s *IngestSimulatePipelineService) BodyJson(body interface{}) *IngestSimulatePipelineService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the simulate definition, defined as a string.\nfunc (s *IngestSimulatePipelineService) BodyString(body string) *IngestSimulatePipelineService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *IngestSimulatePipelineService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\t// Build URL\n\tif s.id != \"\" {\n\t\tpath, err = uritemplates.Expand(\"/_ingest/pipeline/{id}/_simulate\", map[string]string{\n\t\t\t\"id\": s.id,\n\t\t})\n\t} else {\n\t\tpath = \"/_ingest/pipeline/_simulate\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.verbose; v != nil {\n\t\tparams.Set(\"verbose\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *IngestSimulatePipelineService) Validate() error {\n\tvar invalid []string\n\tif s.bodyString == \"\" && s.bodyJson == nil {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *IngestSimulatePipelineService) Do(ctx context.Context) (*IngestSimulatePipelineResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(IngestSimulatePipelineResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// IngestSimulatePipelineResponse is the response of IngestSimulatePipeline.Do.\ntype IngestSimulatePipelineResponse struct {\n\tDocs []*IngestSimulateDocumentResult `json:\"docs\"`\n}\n\ntype IngestSimulateDocumentResult struct {\n\tDoc              map[string]interface{}           `json:\"doc\"`\n\tProcessorResults []*IngestSimulateProcessorResult `json:\"processor_results\"`\n}\n\ntype IngestSimulateProcessorResult struct {\n\tProcessorTag string                 `json:\"tag\"`\n\tDoc          map[string]interface{} `json:\"doc\"`\n}\n"
  },
  {
    "path": "ingest_simulate_pipeline_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestIngestSimulatePipelineURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tId       string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"/_ingest/pipeline/_simulate\",\n\t\t},\n\t\t{\n\t\t\t\"my-pipeline-id\",\n\t\t\t\"/_ingest/pipeline/my-pipeline-id/_simulate\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.IngestSimulatePipeline().Id(test.Id).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "inner_hit.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// InnerHit implements a simple join for parent/child, nested, and even\n// top-level documents in Elasticsearch.\n// It is an experimental feature for Elasticsearch versions 1.5 (or greater).\n// See http://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-inner-hits.html\n// for documentation.\n//\n// See the tests for SearchSource, HasChildFilter, HasChildQuery,\n// HasParentFilter, HasParentQuery, NestedFilter, and NestedQuery\n// for usage examples.\ntype InnerHit struct {\n\tsource *SearchSource\n\tpath   string\n\ttyp    string\n\n\tname string\n}\n\n// NewInnerHit creates a new InnerHit.\nfunc NewInnerHit() *InnerHit {\n\treturn &InnerHit{source: NewSearchSource()}\n}\n\nfunc (hit *InnerHit) Path(path string) *InnerHit {\n\thit.path = path\n\treturn hit\n}\n\nfunc (hit *InnerHit) Type(typ string) *InnerHit {\n\thit.typ = typ\n\treturn hit\n}\n\nfunc (hit *InnerHit) Query(query Query) *InnerHit {\n\thit.source.Query(query)\n\treturn hit\n}\n\nfunc (hit *InnerHit) Collapse(collapse *CollapseBuilder) *InnerHit {\n\thit.source.Collapse(collapse)\n\treturn hit\n}\n\nfunc (hit *InnerHit) From(from int) *InnerHit {\n\thit.source.From(from)\n\treturn hit\n}\n\nfunc (hit *InnerHit) Size(size int) *InnerHit {\n\thit.source.Size(size)\n\treturn hit\n}\n\nfunc (hit *InnerHit) TrackScores(trackScores bool) *InnerHit {\n\thit.source.TrackScores(trackScores)\n\treturn hit\n}\n\nfunc (hit *InnerHit) Explain(explain bool) *InnerHit {\n\thit.source.Explain(explain)\n\treturn hit\n}\n\nfunc (hit *InnerHit) Version(version bool) *InnerHit {\n\thit.source.Version(version)\n\treturn hit\n}\n\nfunc (hit *InnerHit) StoredField(storedFieldName string) *InnerHit {\n\thit.source.StoredField(storedFieldName)\n\treturn hit\n}\n\nfunc (hit *InnerHit) StoredFields(storedFieldNames ...string) *InnerHit {\n\thit.source.StoredFields(storedFieldNames...)\n\treturn hit\n}\n\nfunc (hit *InnerHit) NoStoredFields() *InnerHit {\n\thit.source.NoStoredFields()\n\treturn hit\n}\n\nfunc (hit *InnerHit) FetchSource(fetchSource bool) *InnerHit {\n\thit.source.FetchSource(fetchSource)\n\treturn hit\n}\n\nfunc (hit *InnerHit) FetchSourceContext(fetchSourceContext *FetchSourceContext) *InnerHit {\n\thit.source.FetchSourceContext(fetchSourceContext)\n\treturn hit\n}\n\nfunc (hit *InnerHit) DocvalueFields(docvalueFields ...string) *InnerHit {\n\thit.source.DocvalueFields(docvalueFields...)\n\treturn hit\n}\n\nfunc (hit *InnerHit) DocvalueFieldsWithFormat(docvalueFields ...DocvalueField) *InnerHit {\n\thit.source.DocvalueFieldsWithFormat(docvalueFields...)\n\treturn hit\n}\n\nfunc (hit *InnerHit) DocvalueField(docvalueField string) *InnerHit {\n\thit.source.DocvalueField(docvalueField)\n\treturn hit\n}\n\nfunc (hit *InnerHit) DocvalueFieldWithFormat(docvalueField DocvalueField) *InnerHit {\n\thit.source.DocvalueFieldWithFormat(docvalueField)\n\treturn hit\n}\n\nfunc (hit *InnerHit) ScriptFields(scriptFields ...*ScriptField) *InnerHit {\n\thit.source.ScriptFields(scriptFields...)\n\treturn hit\n}\n\nfunc (hit *InnerHit) ScriptField(scriptField *ScriptField) *InnerHit {\n\thit.source.ScriptField(scriptField)\n\treturn hit\n}\n\nfunc (hit *InnerHit) Sort(field string, ascending bool) *InnerHit {\n\thit.source.Sort(field, ascending)\n\treturn hit\n}\n\nfunc (hit *InnerHit) SortWithInfo(info SortInfo) *InnerHit {\n\thit.source.SortWithInfo(info)\n\treturn hit\n}\n\nfunc (hit *InnerHit) SortBy(sorter ...Sorter) *InnerHit {\n\thit.source.SortBy(sorter...)\n\treturn hit\n}\n\nfunc (hit *InnerHit) Highlight(highlight *Highlight) *InnerHit {\n\thit.source.Highlight(highlight)\n\treturn hit\n}\n\nfunc (hit *InnerHit) Highlighter() *Highlight {\n\treturn hit.source.Highlighter()\n}\n\nfunc (hit *InnerHit) Name(name string) *InnerHit {\n\thit.name = name\n\treturn hit\n}\n\nfunc (hit *InnerHit) Source() (interface{}, error) {\n\tsrc, err := hit.source.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsource, ok := src.(map[string]interface{})\n\tif !ok {\n\t\treturn nil, nil\n\t}\n\n\t// Notice that hit.typ and hit.path are not exported here.\n\t// They are only used with SearchSource and serialized there.\n\n\tif hit.name != \"\" {\n\t\tsource[\"name\"] = hit.name\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "inner_hit_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestInnerHitEmpty(t *testing.T) {\n\thit := NewInnerHit()\n\tsrc, err := hit.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestInnerHitWithName(t *testing.T) {\n\thit := NewInnerHit().Name(\"comments\")\n\tsrc, err := hit.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"name\":\"comments\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestInnerHitSecondLevelCollapse(t *testing.T) {\n\thit := NewInnerHit().Name(\"by_location\").Size(3).Collapse(NewCollapseBuilder(\"user.id\"))\n\tsrc, err := hit.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"collapse\":{\"field\":\"user.id\"},\"name\":\"by_location\",\"size\":3}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "logger.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// Logger specifies the interface for all log operations.\ntype Logger interface {\n\tPrintf(format string, v ...interface{})\n}\n"
  },
  {
    "path": "mget.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// MgetService allows to get multiple documents based on an index,\n// type (optional) and id (possibly routing). The response includes\n// a docs array with all the fetched documents, each element similar\n// in structure to a document provided by the Get API.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-multi-get.html\n// for details.\ntype MgetService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tpreference   string\n\trealtime     *bool\n\trefresh      string\n\trouting      string\n\tstoredFields []string\n\titems        []*MultiGetItem\n}\n\n// NewMgetService initializes a new Multi GET API request call.\nfunc NewMgetService(client *Client) *MgetService {\n\tbuilder := &MgetService{\n\t\tclient: client,\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *MgetService) Pretty(pretty bool) *MgetService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *MgetService) Human(human bool) *MgetService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *MgetService) ErrorTrace(errorTrace bool) *MgetService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *MgetService) FilterPath(filterPath ...string) *MgetService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *MgetService) Header(name string, value string) *MgetService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *MgetService) Headers(headers http.Header) *MgetService {\n\ts.headers = headers\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be performed\n// on (default: random).\nfunc (s *MgetService) Preference(preference string) *MgetService {\n\ts.preference = preference\n\treturn s\n}\n\n// Refresh the shard containing the document before performing the operation.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *MgetService) Refresh(refresh string) *MgetService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// Realtime specifies whether to perform the operation in realtime or search mode.\nfunc (s *MgetService) Realtime(realtime bool) *MgetService {\n\ts.realtime = &realtime\n\treturn s\n}\n\n// Routing is the specific routing value.\nfunc (s *MgetService) Routing(routing string) *MgetService {\n\ts.routing = routing\n\treturn s\n}\n\n// StoredFields is a list of fields to return in the response.\nfunc (s *MgetService) StoredFields(storedFields ...string) *MgetService {\n\ts.storedFields = append(s.storedFields, storedFields...)\n\treturn s\n}\n\n// Add an item to the request.\nfunc (s *MgetService) Add(items ...*MultiGetItem) *MgetService {\n\ts.items = append(s.items, items...)\n\treturn s\n}\n\n// Source returns the request body, which will be serialized into JSON.\nfunc (s *MgetService) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\titems := make([]interface{}, len(s.items))\n\tfor i, item := range s.items {\n\t\tsrc, err := item.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\titems[i] = src\n\t}\n\tsource[\"docs\"] = items\n\treturn source, nil\n}\n\n// Do executes the request.\nfunc (s *MgetService) Do(ctx context.Context) (*MgetResponse, error) {\n\t// Build url\n\tpath := \"/_mget\"\n\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.realtime != nil {\n\t\tparams.Add(\"realtime\", fmt.Sprintf(\"%v\", *s.realtime))\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Add(\"preference\", s.preference)\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Add(\"refresh\", s.refresh)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif len(s.storedFields) > 0 {\n\t\tparams.Set(\"stored_fields\", strings.Join(s.storedFields, \",\"))\n\t}\n\n\t// Set body\n\tbody, err := s.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return result\n\tret := new(MgetResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Multi Get Item --\n\n// MultiGetItem is a single document to retrieve via the MgetService.\ntype MultiGetItem struct {\n\tindex        string\n\ttyp          string\n\tid           string\n\trouting      string\n\tstoredFields []string\n\tversion      *int64 // see org.elasticsearch.common.lucene.uid.Versions\n\tversionType  string // see org.elasticsearch.index.VersionType\n\tfsc          *FetchSourceContext\n}\n\n// NewMultiGetItem initializes a new, single item for a Multi GET request.\nfunc NewMultiGetItem() *MultiGetItem {\n\treturn &MultiGetItem{}\n}\n\n// Index specifies the index name.\nfunc (item *MultiGetItem) Index(index string) *MultiGetItem {\n\titem.index = index\n\treturn item\n}\n\n// Type specifies the type name.\nfunc (item *MultiGetItem) Type(typ string) *MultiGetItem {\n\titem.typ = typ\n\treturn item\n}\n\n// Id specifies the identifier of the document.\nfunc (item *MultiGetItem) Id(id string) *MultiGetItem {\n\titem.id = id\n\treturn item\n}\n\n// Routing is the specific routing value.\nfunc (item *MultiGetItem) Routing(routing string) *MultiGetItem {\n\titem.routing = routing\n\treturn item\n}\n\n// StoredFields is a list of fields to return in the response.\nfunc (item *MultiGetItem) StoredFields(storedFields ...string) *MultiGetItem {\n\titem.storedFields = append(item.storedFields, storedFields...)\n\treturn item\n}\n\n// Version can be MatchAny (-3), MatchAnyPre120 (0), NotFound (-1),\n// or NotSet (-2). These are specified in org.elasticsearch.common.lucene.uid.Versions.\n// The default in Elasticsearch is MatchAny (-3).\nfunc (item *MultiGetItem) Version(version int64) *MultiGetItem {\n\titem.version = &version\n\treturn item\n}\n\n// VersionType can be \"internal\", \"external\", \"external_gt\", or \"external_gte\".\n// See org.elasticsearch.index.VersionType in Elasticsearch source.\n// It is \"internal\" by default.\nfunc (item *MultiGetItem) VersionType(versionType string) *MultiGetItem {\n\titem.versionType = versionType\n\treturn item\n}\n\n// FetchSource allows to specify source filtering.\nfunc (item *MultiGetItem) FetchSource(fetchSourceContext *FetchSourceContext) *MultiGetItem {\n\titem.fsc = fetchSourceContext\n\treturn item\n}\n\n// Source returns the serialized JSON to be sent to Elasticsearch as\n// part of a MultiGet search.\nfunc (item *MultiGetItem) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tsource[\"_id\"] = item.id\n\n\tif item.index != \"\" {\n\t\tsource[\"_index\"] = item.index\n\t}\n\tif item.typ != \"\" {\n\t\tsource[\"_type\"] = item.typ\n\t}\n\tif item.fsc != nil {\n\t\tsrc, err := item.fsc.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"_source\"] = src\n\t}\n\tif item.routing != \"\" {\n\t\tsource[\"routing\"] = item.routing\n\t}\n\tif len(item.storedFields) > 0 {\n\t\tsource[\"stored_fields\"] = strings.Join(item.storedFields, \",\")\n\t}\n\tif item.version != nil {\n\t\tsource[\"version\"] = fmt.Sprintf(\"%d\", *item.version)\n\t}\n\tif item.versionType != \"\" {\n\t\tsource[\"version_type\"] = item.versionType\n\t}\n\n\treturn source, nil\n}\n\n// -- Result of a Multi Get request.\n\n// MgetResponse is the outcome of a Multi GET API request.\ntype MgetResponse struct {\n\tDocs []*GetResult `json:\"docs,omitempty\"`\n}\n"
  },
  {
    "path": "mget_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMultiGet(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add some documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Count documents\n\tcount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 3 {\n\t\tt.Errorf(\"expected Count = %d; got %d\", 3, count)\n\t}\n\n\t// Get documents 1 and 3\n\tres, err := client.MultiGet().\n\t\tAdd(NewMultiGetItem().Index(testIndexName).Id(\"1\")).\n\t\tAdd(NewMultiGetItem().Index(testIndexName).Id(\"3\")).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected result to be != nil; got nil\")\n\t}\n\tif res.Docs == nil {\n\t\tt.Fatal(\"expected result docs to be != nil; got nil\")\n\t}\n\tif len(res.Docs) != 2 {\n\t\tt.Fatalf(\"expected to have 2 docs; got %d\", len(res.Docs))\n\t}\n\n\titem := res.Docs[0]\n\tif item.Error != nil {\n\t\tt.Errorf(\"expected no error on item 0; got %v\", item.Error)\n\t}\n\tif item.Source == nil {\n\t\tt.Errorf(\"expected Source != nil; got %v\", item.Source)\n\t}\n\tvar doc tweet\n\tif err := json.Unmarshal(item.Source, &doc); err != nil {\n\t\tt.Fatalf(\"expected to unmarshal item Source; got %v\", err)\n\t}\n\tif doc.Message != tweet1.Message {\n\t\tt.Errorf(\"expected Message of first tweet to be %q; got %q\", tweet1.Message, doc.Message)\n\t}\n\n\titem = res.Docs[1]\n\tif item.Error != nil {\n\t\tt.Errorf(\"expected no error on item 1; got %v\", item.Error)\n\t}\n\tif item.Source == nil {\n\t\tt.Errorf(\"expected Source != nil; got %v\", item.Source)\n\t}\n\tif err := json.Unmarshal(item.Source, &doc); err != nil {\n\t\tt.Fatalf(\"expected to unmarshal item Source; got %v\", err)\n\t}\n\tif doc.Message != tweet3.Message {\n\t\tt.Errorf(\"expected Message of second tweet to be %q; got %q\", tweet3.Message, doc.Message)\n\t}\n}\n"
  },
  {
    "path": "msearch.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// MultiSearch executes one or more searches in one roundtrip.\ntype MultiSearchService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trequests              []*SearchRequest\n\tindices               []string\n\tmaxConcurrentRequests *int\n\tpreFilterShardSize    *int\n}\n\nfunc NewMultiSearchService(client *Client) *MultiSearchService {\n\tbuilder := &MultiSearchService{\n\t\tclient: client,\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *MultiSearchService) Pretty(pretty bool) *MultiSearchService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *MultiSearchService) Human(human bool) *MultiSearchService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *MultiSearchService) ErrorTrace(errorTrace bool) *MultiSearchService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *MultiSearchService) FilterPath(filterPath ...string) *MultiSearchService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *MultiSearchService) Header(name string, value string) *MultiSearchService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *MultiSearchService) Headers(headers http.Header) *MultiSearchService {\n\ts.headers = headers\n\treturn s\n}\n\nfunc (s *MultiSearchService) Add(requests ...*SearchRequest) *MultiSearchService {\n\ts.requests = append(s.requests, requests...)\n\treturn s\n}\n\nfunc (s *MultiSearchService) Index(indices ...string) *MultiSearchService {\n\ts.indices = append(s.indices, indices...)\n\treturn s\n}\n\nfunc (s *MultiSearchService) MaxConcurrentSearches(max int) *MultiSearchService {\n\ts.maxConcurrentRequests = &max\n\treturn s\n}\n\nfunc (s *MultiSearchService) PreFilterShardSize(size int) *MultiSearchService {\n\ts.preFilterShardSize = &size\n\treturn s\n}\n\nfunc (s *MultiSearchService) Do(ctx context.Context) (*MultiSearchResult, error) {\n\t// Build url\n\tpath := \"/_msearch\"\n\n\t// Parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.maxConcurrentRequests; v != nil {\n\t\tparams.Set(\"max_concurrent_searches\", fmt.Sprintf(\"%v\", *v))\n\t}\n\tif v := s.preFilterShardSize; v != nil {\n\t\tparams.Set(\"pre_filter_shard_size\", fmt.Sprintf(\"%v\", *v))\n\t}\n\n\t// Set body\n\tvar lines []string\n\tfor _, sr := range s.requests {\n\t\t// Set default indices if not specified in the request\n\t\tif !sr.HasIndices() && len(s.indices) > 0 {\n\t\t\tsr = sr.Index(s.indices...)\n\t\t}\n\n\t\theader, err := json.Marshal(sr.header())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbody, err := sr.Body()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tlines = append(lines, string(header))\n\t\tlines = append(lines, body)\n\t}\n\tbody := strings.Join(lines, \"\\n\") + \"\\n\" // add trailing \\n\n\n\t// Get response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return result\n\tret := new(MultiSearchResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// MultiSearchResult is the outcome of running a multi-search operation.\ntype MultiSearchResult struct {\n\tTookInMillis int64           `json:\"took,omitempty\"` // search time in milliseconds\n\tResponses    []*SearchResult `json:\"responses,omitempty\"`\n}\n"
  },
  {
    "path": "msearch_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t_ \"net/http\"\n\t\"testing\"\n)\n\nfunc TestMultiSearch(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\t// client := setupTestClientAndCreateIndexAndLog(t)\n\n\ttweet1 := tweet{\n\t\tUser:    \"olivere\",\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tTags:    []string{\"golang\", \"elasticsearch\"},\n\t}\n\ttweet2 := tweet{\n\t\tUser:    \"olivere\",\n\t\tMessage: \"Another unrelated topic.\",\n\t\tTags:    []string{\"golang\"},\n\t}\n\ttweet3 := tweet{\n\t\tUser:    \"sandrae\",\n\t\tMessage: \"Cycling is fun.\",\n\t\tTags:    []string{\"sports\", \"cycling\"},\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Spawn two search queries with one roundtrip\n\tq1 := NewMatchAllQuery()\n\tq2 := NewTermQuery(\"tags\", \"golang\")\n\n\tsreq1 := NewSearchRequest().Index(testIndexName, testIndexName2).\n\t\tSource(NewSearchSource().Query(q1).Size(10))\n\tsreq2 := NewSearchRequest().Index(testIndexName).\n\t\tSource(NewSearchSource().Query(q2))\n\n\tsearchResult, err := client.MultiSearch().\n\t\tAdd(sreq1, sreq2).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Responses == nil {\n\t\tt.Fatal(\"expected responses != nil; got nil\")\n\t}\n\tif len(searchResult.Responses) != 2 {\n\t\tt.Fatalf(\"expected 2 responses; got %d\", len(searchResult.Responses))\n\t}\n\n\tsres := searchResult.Responses[0]\n\tif sres.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got nil\")\n\t}\n\tif sres.TotalHits() != 3 {\n\t\tt.Errorf(\"expected TotalHits() = %d; got %d\", 3, sres.TotalHits())\n\t}\n\tif len(sres.Hits.Hits) != 3 {\n\t\tt.Errorf(\"expected len(Hits.Hits) = %d; got %d\", 3, len(sres.Hits.Hits))\n\t}\n\tfor _, hit := range sres.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\tsres = searchResult.Responses[1]\n\tif sres.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got nil\")\n\t}\n\tif sres.TotalHits() != 2 {\n\t\tt.Errorf(\"expected TotalHits() = %d; got %d\", 2, sres.TotalHits())\n\t}\n\tif len(sres.Hits.Hits) != 2 {\n\t\tt.Errorf(\"expected len(Hits.Hits) = %d; got %d\", 2, len(sres.Hits.Hits))\n\t}\n\tfor _, hit := range sres.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc TestMultiSearchWithStrings(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\t// client := setupTestClientAndCreateIndexAndLog(t)\n\n\ttweet1 := tweet{\n\t\tUser:    \"olivere\",\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tTags:    []string{\"golang\", \"elasticsearch\"},\n\t}\n\ttweet2 := tweet{\n\t\tUser:    \"olivere\",\n\t\tMessage: \"Another unrelated topic.\",\n\t\tTags:    []string{\"golang\"},\n\t}\n\ttweet3 := tweet{\n\t\tUser:    \"sandrae\",\n\t\tMessage: \"Cycling is fun.\",\n\t\tTags:    []string{\"sports\", \"cycling\"},\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Spawn two search queries with one roundtrip\n\tsreq1 := NewSearchRequest().Index(testIndexName, testIndexName2).\n\t\tSource(`{\"query\":{\"match_all\":{}}}`)\n\tsreq2 := NewSearchRequest().Index(testIndexName).\n\t\tSource(`{\"query\":{\"term\":{\"tags\":\"golang\"}}}`)\n\n\tsearchResult, err := client.MultiSearch().\n\t\tAdd(sreq1, sreq2).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Responses == nil {\n\t\tt.Fatal(\"expected responses != nil; got nil\")\n\t}\n\tif len(searchResult.Responses) != 2 {\n\t\tt.Fatalf(\"expected 2 responses; got %d\", len(searchResult.Responses))\n\t}\n\n\tsres := searchResult.Responses[0]\n\tif sres.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got nil\")\n\t}\n\tif sres.TotalHits() != 3 {\n\t\tt.Errorf(\"expected TotalHits() = %d; got %d\", 3, sres.TotalHits())\n\t}\n\tif len(sres.Hits.Hits) != 3 {\n\t\tt.Errorf(\"expected len(Hits.Hits) = %d; got %d\", 3, len(sres.Hits.Hits))\n\t}\n\tfor _, hit := range sres.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\tsres = searchResult.Responses[1]\n\tif sres.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got nil\")\n\t}\n\tif sres.TotalHits() != 2 {\n\t\tt.Errorf(\"expected TotalHits() = %d; got %d\", 2, sres.TotalHits())\n\t}\n\tif len(sres.Hits.Hits) != 2 {\n\t\tt.Errorf(\"expected len(Hits.Hits) = %d; got %d\", 2, len(sres.Hits.Hits))\n\t}\n\tfor _, hit := range sres.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc TestMultiSearchWithOneRequest(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser:    \"olivere\",\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tTags:    []string{\"golang\", \"elasticsearch\"},\n\t}\n\ttweet2 := tweet{\n\t\tUser:    \"olivere\",\n\t\tMessage: \"Another unrelated topic.\",\n\t\tTags:    []string{\"golang\"},\n\t}\n\ttweet3 := tweet{\n\t\tUser:    \"sandrae\",\n\t\tMessage: \"Cycling is fun.\",\n\t\tTags:    []string{\"sports\", \"cycling\"},\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Spawn two search queries with one roundtrip\n\tquery := NewMatchAllQuery()\n\tsource := NewSearchSource().Query(query).Size(10)\n\tsreq := NewSearchRequest().Source(source)\n\n\tsearchResult, err := client.MultiSearch().\n\t\tIndex(testIndexName).\n\t\tAdd(sreq).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Responses == nil {\n\t\tt.Fatal(\"expected responses != nil; got nil\")\n\t}\n\tif len(searchResult.Responses) != 1 {\n\t\tt.Fatalf(\"expected 1 responses; got %d\", len(searchResult.Responses))\n\t}\n\n\tsres := searchResult.Responses[0]\n\tif sres.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got nil\")\n\t}\n\tif sres.TotalHits() != 3 {\n\t\tt.Errorf(\"expected TotalHits() = %d; got %d\", 3, sres.TotalHits())\n\t}\n\tif len(sres.Hits.Hits) != 3 {\n\t\tt.Errorf(\"expected len(Hits.Hits) = %d; got %d\", 3, len(sres.Hits.Hits))\n\t}\n\tfor _, hit := range sres.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "mtermvectors.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// MultiTermvectorService returns information and statistics on terms in the\n// fields of a particular document. The document could be stored in the\n// index or artificially provided by the user.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-multi-termvectors.html\n// for documentation.\ntype MultiTermvectorService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex           string\n\ttyp             string\n\tfieldStatistics *bool\n\tfields          []string\n\tids             []string\n\toffsets         *bool\n\tparent          string\n\tpayloads        *bool\n\tpositions       *bool\n\tpreference      string\n\trealtime        *bool\n\trouting         string\n\ttermStatistics  *bool\n\tversion         interface{}\n\tversionType     string\n\tbodyJson        interface{}\n\tbodyString      string\n\tdocs            []*MultiTermvectorItem\n}\n\n// NewMultiTermvectorService creates a new MultiTermvectorService.\nfunc NewMultiTermvectorService(client *Client) *MultiTermvectorService {\n\treturn &MultiTermvectorService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *MultiTermvectorService) Pretty(pretty bool) *MultiTermvectorService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *MultiTermvectorService) Human(human bool) *MultiTermvectorService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *MultiTermvectorService) ErrorTrace(errorTrace bool) *MultiTermvectorService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *MultiTermvectorService) FilterPath(filterPath ...string) *MultiTermvectorService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *MultiTermvectorService) Header(name string, value string) *MultiTermvectorService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *MultiTermvectorService) Headers(headers http.Header) *MultiTermvectorService {\n\ts.headers = headers\n\treturn s\n}\n\n// Add adds documents to MultiTermvectors service.\nfunc (s *MultiTermvectorService) Add(docs ...*MultiTermvectorItem) *MultiTermvectorService {\n\ts.docs = append(s.docs, docs...)\n\treturn s\n}\n\n// Index in which the document resides.\nfunc (s *MultiTermvectorService) Index(index string) *MultiTermvectorService {\n\ts.index = index\n\treturn s\n}\n\n// Type of the document.\nfunc (s *MultiTermvectorService) Type(typ string) *MultiTermvectorService {\n\ts.typ = typ\n\treturn s\n}\n\n// FieldStatistics specifies if document count, sum of document frequencies and sum of total term frequencies should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".\nfunc (s *MultiTermvectorService) FieldStatistics(fieldStatistics bool) *MultiTermvectorService {\n\ts.fieldStatistics = &fieldStatistics\n\treturn s\n}\n\n// Fields is a comma-separated list of fields to return. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".\nfunc (s *MultiTermvectorService) Fields(fields []string) *MultiTermvectorService {\n\ts.fields = fields\n\treturn s\n}\n\n// Ids is a comma-separated list of documents ids. You must define ids as parameter or set \"ids\" or \"docs\" in the request body.\nfunc (s *MultiTermvectorService) Ids(ids []string) *MultiTermvectorService {\n\ts.ids = ids\n\treturn s\n}\n\n// Offsets specifies if term offsets should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".\nfunc (s *MultiTermvectorService) Offsets(offsets bool) *MultiTermvectorService {\n\ts.offsets = &offsets\n\treturn s\n}\n\n// Parent id of documents. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".\nfunc (s *MultiTermvectorService) Parent(parent string) *MultiTermvectorService {\n\ts.parent = parent\n\treturn s\n}\n\n// Payloads specifies if term payloads should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".\nfunc (s *MultiTermvectorService) Payloads(payloads bool) *MultiTermvectorService {\n\ts.payloads = &payloads\n\treturn s\n}\n\n// Positions specifies if term positions should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".\nfunc (s *MultiTermvectorService) Positions(positions bool) *MultiTermvectorService {\n\ts.positions = &positions\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be performed on (default: random). Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".\nfunc (s *MultiTermvectorService) Preference(preference string) *MultiTermvectorService {\n\ts.preference = preference\n\treturn s\n}\n\n// Realtime specifies if requests are real-time as opposed to near-real-time (default: true).\nfunc (s *MultiTermvectorService) Realtime(realtime bool) *MultiTermvectorService {\n\ts.realtime = &realtime\n\treturn s\n}\n\n// Routing specific routing value. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".\nfunc (s *MultiTermvectorService) Routing(routing string) *MultiTermvectorService {\n\ts.routing = routing\n\treturn s\n}\n\n// TermStatistics specifies if total term frequency and document frequency should be returned. Applies to all returned documents unless otherwise specified in body \"params\" or \"docs\".\nfunc (s *MultiTermvectorService) TermStatistics(termStatistics bool) *MultiTermvectorService {\n\ts.termStatistics = &termStatistics\n\treturn s\n}\n\n// Version is explicit version number for concurrency control.\nfunc (s *MultiTermvectorService) Version(version interface{}) *MultiTermvectorService {\n\ts.version = version\n\treturn s\n}\n\n// VersionType is specific version type.\nfunc (s *MultiTermvectorService) VersionType(versionType string) *MultiTermvectorService {\n\ts.versionType = versionType\n\treturn s\n}\n\n// BodyJson is documented as: Define ids, documents, parameters or a list of parameters per document here. You must at least provide a list of document ids. See documentation..\nfunc (s *MultiTermvectorService) BodyJson(body interface{}) *MultiTermvectorService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is documented as: Define ids, documents, parameters or a list of parameters per document here. You must at least provide a list of document ids. See documentation..\nfunc (s *MultiTermvectorService) BodyString(body string) *MultiTermvectorService {\n\ts.bodyString = body\n\treturn s\n}\n\nfunc (s *MultiTermvectorService) Source() interface{} {\n\tsource := make(map[string]interface{})\n\tdocs := make([]interface{}, len(s.docs))\n\tfor i, doc := range s.docs {\n\t\tdocs[i] = doc.Source()\n\t}\n\tsource[\"docs\"] = docs\n\treturn source\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *MultiTermvectorService) buildURL() (string, url.Values, error) {\n\tvar path string\n\tvar err error\n\n\tif s.index != \"\" && s.typ != \"\" {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/_mtermvectors\", map[string]string{\n\t\t\t\"index\": s.index,\n\t\t\t\"type\":  s.typ,\n\t\t})\n\t} else if s.index != \"\" && s.typ == \"\" {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_mtermvectors\", map[string]string{\n\t\t\t\"index\": s.index,\n\t\t})\n\t} else {\n\t\tpath = \"/_mtermvectors\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.fieldStatistics != nil {\n\t\tparams.Set(\"field_statistics\", fmt.Sprintf(\"%v\", *s.fieldStatistics))\n\t}\n\tif len(s.fields) > 0 {\n\t\tparams.Set(\"fields\", strings.Join(s.fields, \",\"))\n\t}\n\tif len(s.ids) > 0 {\n\t\tparams.Set(\"ids\", strings.Join(s.ids, \",\"))\n\t}\n\tif s.offsets != nil {\n\t\tparams.Set(\"offsets\", fmt.Sprintf(\"%v\", *s.offsets))\n\t}\n\tif s.parent != \"\" {\n\t\tparams.Set(\"parent\", s.parent)\n\t}\n\tif s.payloads != nil {\n\t\tparams.Set(\"payloads\", fmt.Sprintf(\"%v\", *s.payloads))\n\t}\n\tif s.positions != nil {\n\t\tparams.Set(\"positions\", fmt.Sprintf(\"%v\", *s.positions))\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif s.realtime != nil {\n\t\tparams.Set(\"realtime\", fmt.Sprintf(\"%v\", *s.realtime))\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.termStatistics != nil {\n\t\tparams.Set(\"term_statistics\", fmt.Sprintf(\"%v\", *s.termStatistics))\n\t}\n\tif s.version != nil {\n\t\tparams.Set(\"version\", fmt.Sprintf(\"%v\", s.version))\n\t}\n\tif s.versionType != \"\" {\n\t\tparams.Set(\"version_type\", s.versionType)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *MultiTermvectorService) Validate() error {\n\tvar invalid []string\n\tif s.index == \"\" && s.typ != \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *MultiTermvectorService) Do(ctx context.Context) (*MultiTermvectorResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else if len(s.bodyString) > 0 {\n\t\tbody = s.bodyString\n\t} else {\n\t\tbody = s.Source()\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(MultiTermvectorResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// MultiTermvectorResponse is the response of MultiTermvectorService.Do.\ntype MultiTermvectorResponse struct {\n\tDocs []*TermvectorsResponse `json:\"docs\"`\n}\n\n// -- MultiTermvectorItem --\n\n// MultiTermvectorItem is a single document to retrieve via MultiTermvectorService.\ntype MultiTermvectorItem struct {\n\tindex            string\n\ttyp              string\n\tid               string\n\tdoc              interface{}\n\tfieldStatistics  *bool\n\tfields           []string\n\tperFieldAnalyzer map[string]string\n\toffsets          *bool\n\tparent           string\n\tpayloads         *bool\n\tpositions        *bool\n\tpreference       string\n\trealtime         *bool\n\trouting          string\n\ttermStatistics   *bool\n}\n\nfunc NewMultiTermvectorItem() *MultiTermvectorItem {\n\treturn &MultiTermvectorItem{}\n}\n\nfunc (s *MultiTermvectorItem) Index(index string) *MultiTermvectorItem {\n\ts.index = index\n\treturn s\n}\n\nfunc (s *MultiTermvectorItem) Type(typ string) *MultiTermvectorItem {\n\ts.typ = typ\n\treturn s\n}\n\nfunc (s *MultiTermvectorItem) Id(id string) *MultiTermvectorItem {\n\ts.id = id\n\treturn s\n}\n\n// Doc is the document to analyze.\nfunc (s *MultiTermvectorItem) Doc(doc interface{}) *MultiTermvectorItem {\n\ts.doc = doc\n\treturn s\n}\n\n// FieldStatistics specifies if document count, sum of document frequencies\n// and sum of total term frequencies should be returned.\nfunc (s *MultiTermvectorItem) FieldStatistics(fieldStatistics bool) *MultiTermvectorItem {\n\ts.fieldStatistics = &fieldStatistics\n\treturn s\n}\n\n// Fields a list of fields to return.\nfunc (s *MultiTermvectorItem) Fields(fields ...string) *MultiTermvectorItem {\n\tif s.fields == nil {\n\t\ts.fields = make([]string, 0)\n\t}\n\ts.fields = append(s.fields, fields...)\n\treturn s\n}\n\n// PerFieldAnalyzer allows to specify a different analyzer than the one\n// at the field.\nfunc (s *MultiTermvectorItem) PerFieldAnalyzer(perFieldAnalyzer map[string]string) *MultiTermvectorItem {\n\ts.perFieldAnalyzer = perFieldAnalyzer\n\treturn s\n}\n\n// Offsets specifies if term offsets should be returned.\nfunc (s *MultiTermvectorItem) Offsets(offsets bool) *MultiTermvectorItem {\n\ts.offsets = &offsets\n\treturn s\n}\n\n// Parent id of documents.\nfunc (s *MultiTermvectorItem) Parent(parent string) *MultiTermvectorItem {\n\ts.parent = parent\n\treturn s\n}\n\n// Payloads specifies if term payloads should be returned.\nfunc (s *MultiTermvectorItem) Payloads(payloads bool) *MultiTermvectorItem {\n\ts.payloads = &payloads\n\treturn s\n}\n\n// Positions specifies if term positions should be returned.\nfunc (s *MultiTermvectorItem) Positions(positions bool) *MultiTermvectorItem {\n\ts.positions = &positions\n\treturn s\n}\n\n// Preference specify the node or shard the operation\n// should be performed on (default: random).\nfunc (s *MultiTermvectorItem) Preference(preference string) *MultiTermvectorItem {\n\ts.preference = preference\n\treturn s\n}\n\n// Realtime specifies if request is real-time as opposed to\n// near-real-time (default: true).\nfunc (s *MultiTermvectorItem) Realtime(realtime bool) *MultiTermvectorItem {\n\ts.realtime = &realtime\n\treturn s\n}\n\n// Routing is a specific routing value.\nfunc (s *MultiTermvectorItem) Routing(routing string) *MultiTermvectorItem {\n\ts.routing = routing\n\treturn s\n}\n\n// TermStatistics specifies if total term frequency and document frequency\n// should be returned.\nfunc (s *MultiTermvectorItem) TermStatistics(termStatistics bool) *MultiTermvectorItem {\n\ts.termStatistics = &termStatistics\n\treturn s\n}\n\n// Source returns the serialized JSON to be sent to Elasticsearch as\n// part of a MultiTermvector.\nfunc (s *MultiTermvectorItem) Source() interface{} {\n\tsource := make(map[string]interface{})\n\n\tsource[\"_id\"] = s.id\n\n\tif s.index != \"\" {\n\t\tsource[\"_index\"] = s.index\n\t}\n\tif s.typ != \"\" {\n\t\tsource[\"_type\"] = s.typ\n\t}\n\tif s.fields != nil {\n\t\tsource[\"fields\"] = s.fields\n\t}\n\tif s.fieldStatistics != nil {\n\t\tsource[\"field_statistics\"] = fmt.Sprintf(\"%v\", *s.fieldStatistics)\n\t}\n\tif s.offsets != nil {\n\t\tsource[\"offsets\"] = s.offsets\n\t}\n\tif s.parent != \"\" {\n\t\tsource[\"parent\"] = s.parent\n\t}\n\tif s.payloads != nil {\n\t\tsource[\"payloads\"] = fmt.Sprintf(\"%v\", *s.payloads)\n\t}\n\tif s.positions != nil {\n\t\tsource[\"positions\"] = fmt.Sprintf(\"%v\", *s.positions)\n\t}\n\tif s.preference != \"\" {\n\t\tsource[\"preference\"] = s.preference\n\t}\n\tif s.realtime != nil {\n\t\tsource[\"realtime\"] = fmt.Sprintf(\"%v\", *s.realtime)\n\t}\n\tif s.routing != \"\" {\n\t\tsource[\"routing\"] = s.routing\n\t}\n\tif s.termStatistics != nil {\n\t\tsource[\"term_statistics\"] = fmt.Sprintf(\"%v\", *s.termStatistics)\n\t}\n\tif s.doc != nil {\n\t\tsource[\"doc\"] = s.doc\n\t}\n\tif s.perFieldAnalyzer != nil && len(s.perFieldAnalyzer) > 0 {\n\t\tsource[\"per_field_analyzer\"] = s.perFieldAnalyzer\n\t}\n\n\treturn source\n}\n"
  },
  {
    "path": "mtermvectors_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestMultiTermVectorsValidateAndBuildURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndex                 string\n\t\tType                  string\n\t\tExpected              string\n\t\tExpectValidateFailure bool\n\t}{\n\t\t// #0: No index, no type\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\t\"/_mtermvectors\",\n\t\t\tfalse,\n\t\t},\n\t\t// #1: Index only\n\t\t{\n\t\t\t\"twitter\",\n\t\t\t\"\",\n\t\t\t\"/twitter/_mtermvectors\",\n\t\t\tfalse,\n\t\t},\n\t\t// #2: Type without index\n\t\t{\n\t\t\t\"\",\n\t\t\t\"doc\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t// #3: Both index and type\n\t\t{\n\t\t\t\"twitter\",\n\t\t\t\"doc\",\n\t\t\t\"/twitter/doc/_mtermvectors\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.MultiTermVectors().Index(test.Index).Type(test.Type)\n\t\t// Validate\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectValidateFailure {\n\t\t\t\tt.Errorf(\"#%d: expected no error, got: %v\", i, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\tif test.ExpectValidateFailure {\n\t\t\t\tt.Errorf(\"#%d: expected error, got: nil\", i)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\t// Build\n\t\t\tpath, _, err := builder.buildURL()\n\t\t\tif err != nil {\n\t\t\t\tt.Errorf(\"#%d: expected no error, got: %v\", i, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"#%d: expected %q; got: %q\", i, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestMultiTermVectorsWithIds(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Count documents\n\tcount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count != 3 {\n\t\tt.Errorf(\"expected Count = %d; got %d\", 3, count)\n\t}\n\n\t// MultiTermVectors by specifying ID by 1 and 3\n\tfield := \"Message\"\n\tres, err := client.MultiTermVectors().\n\t\tIndex(testIndexName).\n\t\tAdd(NewMultiTermvectorItem().Index(testIndexName).Id(\"1\").Fields(field)).\n\t\tAdd(NewMultiTermvectorItem().Index(testIndexName).Id(\"3\").Fields(field)).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected to return information and statistics\")\n\t}\n\tif res.Docs == nil {\n\t\tt.Fatal(\"expected result docs to be != nil; got nil\")\n\t}\n\tif len(res.Docs) != 2 {\n\t\tt.Fatalf(\"expected to have 2 docs; got %d\", len(res.Docs))\n\t}\n}\n"
  },
  {
    "path": "nodes_info.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// NodesInfoService allows to retrieve one or more or all of the\n// cluster nodes information.\n// It is documented at https://www.elastic.co/guide/en/elasticsearch/reference/7.0/cluster-nodes-info.html.\ntype NodesInfoService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tnodeId       []string\n\tmetric       []string\n\tflatSettings *bool\n}\n\n// NewNodesInfoService creates a new NodesInfoService.\nfunc NewNodesInfoService(client *Client) *NodesInfoService {\n\treturn &NodesInfoService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *NodesInfoService) Pretty(pretty bool) *NodesInfoService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *NodesInfoService) Human(human bool) *NodesInfoService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *NodesInfoService) ErrorTrace(errorTrace bool) *NodesInfoService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *NodesInfoService) FilterPath(filterPath ...string) *NodesInfoService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *NodesInfoService) Header(name string, value string) *NodesInfoService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *NodesInfoService) Headers(headers http.Header) *NodesInfoService {\n\ts.headers = headers\n\treturn s\n}\n\n// NodeId is a list of node IDs or names to limit the returned information.\n// Use \"_local\" to return information from the node you're connecting to,\n// leave empty to get information from all nodes.\nfunc (s *NodesInfoService) NodeId(nodeId ...string) *NodesInfoService {\n\ts.nodeId = append(s.nodeId, nodeId...)\n\treturn s\n}\n\n// Metric is a list of metrics you wish returned. Leave empty to return all.\n// Valid metrics are: settings, os, process, jvm, thread_pool, network,\n// transport, http, and plugins.\nfunc (s *NodesInfoService) Metric(metric ...string) *NodesInfoService {\n\ts.metric = append(s.metric, metric...)\n\treturn s\n}\n\n// FlatSettings returns settings in flat format (default: false).\nfunc (s *NodesInfoService) FlatSettings(flatSettings bool) *NodesInfoService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *NodesInfoService) buildURL() (string, url.Values, error) {\n\tvar nodeId, metric string\n\n\tif len(s.nodeId) > 0 {\n\t\tnodeId = strings.Join(s.nodeId, \",\")\n\t} else {\n\t\tnodeId = \"_all\"\n\t}\n\n\tif len(s.metric) > 0 {\n\t\tmetric = strings.Join(s.metric, \",\")\n\t} else {\n\t\tmetric = \"_all\"\n\t}\n\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_nodes/{node_id}/{metric}\", map[string]string{\n\t\t\"node_id\": nodeId,\n\t\t\"metric\":  metric,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.flatSettings != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprintf(\"%v\", *s.flatSettings))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *NodesInfoService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *NodesInfoService) Do(ctx context.Context) (*NodesInfoResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(NodesInfoResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// NodesInfoResponse is the response of NodesInfoService.Do.\ntype NodesInfoResponse struct {\n\tClusterName string                    `json:\"cluster_name\"`\n\tNodes       map[string]*NodesInfoNode `json:\"nodes\"`\n}\n\n// NodesInfoNode represents information about a node in the cluster.\ntype NodesInfoNode struct {\n\t// Name of the node, e.g. \"Mister Fear\"\n\tName string `json:\"name\"`\n\t// TransportAddress, e.g. \"127.0.0.1:9300\"\n\tTransportAddress string `json:\"transport_address\"`\n\t// Host is the host name, e.g. \"macbookair\"\n\tHost string `json:\"host\"`\n\t// IP is the IP address, e.g. \"192.168.1.2\"\n\tIP string `json:\"ip\"`\n\t// Version is the Elasticsearch version running on the node, e.g. \"1.4.3\"\n\tVersion string `json:\"version\"`\n\t// BuildHash is the Elasticsearch build bash, e.g. \"36a29a7\"\n\tBuildHash string `json:\"build_hash\"`\n\n\t// TotalIndexingBuffer represents the total heap allowed to be used to\n\t// hold recently indexed documents before they must be written to disk.\n\tTotalIndexingBuffer int64 `json:\"total_indexing_buffer\"` // e.g. 16gb\n\t// TotalIndexingBufferInBytes is the same as TotalIndexingBuffer, but\n\t// expressed in bytes.\n\tTotalIndexingBufferInBytes string `json:\"total_indexing_buffer_in_bytes\"`\n\n\t// Roles of the node, e.g. [master, ingest, data]\n\tRoles []string `json:\"roles\"`\n\n\t// Attributes of the node.\n\tAttributes map[string]string `json:\"attributes\"`\n\n\t// Settings of the node, e.g. paths and pidfile.\n\tSettings map[string]interface{} `json:\"settings\"`\n\n\t// OS information, e.g. CPU and memory.\n\tOS *NodesInfoNodeOS `json:\"os\"`\n\n\t// Process information, e.g. max file descriptors.\n\tProcess *NodesInfoNodeProcess `json:\"process\"`\n\n\t// JVM information, e.g. VM version.\n\tJVM *NodesInfoNodeJVM `json:\"jvm\"`\n\n\t// ThreadPool information.\n\tThreadPool *NodesInfoNodeThreadPool `json:\"thread_pool\"`\n\n\t// Network information.\n\tTransport *NodesInfoNodeTransport `json:\"transport\"`\n\n\t// HTTP information.\n\tHTTP *NodesInfoNodeHTTP `json:\"http\"`\n\n\t// Plugins information.\n\tPlugins []*NodesInfoNodePlugin `json:\"plugins\"`\n\n\t// Modules information.\n\tModules []*NodesInfoNodeModule `json:\"modules\"`\n\n\t// Ingest information.\n\tIngest *NodesInfoNodeIngest `json:\"ingest\"`\n}\n\n// HasRole returns true if the node fulfills the given role.\nfunc (n *NodesInfoNode) HasRole(role string) bool {\n\tfor _, r := range n.Roles {\n\t\tif r == role {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// IsMaster returns true if the node is a master node.\nfunc (n *NodesInfoNode) IsMaster() bool {\n\treturn n.HasRole(\"master\")\n}\n\n// IsData returns true if the node is a data node.\nfunc (n *NodesInfoNode) IsData() bool {\n\treturn n.HasRole(\"data\")\n}\n\n// IsIngest returns true if the node is an ingest node.\nfunc (n *NodesInfoNode) IsIngest() bool {\n\treturn n.HasRole(\"ingest\")\n}\n\n// NodesInfoNodeOS represents OS-specific details about a node.\ntype NodesInfoNodeOS struct {\n\tRefreshInterval         string `json:\"refresh_interval\"`           // e.g. 1s\n\tRefreshIntervalInMillis int    `json:\"refresh_interval_in_millis\"` // e.g. 1000\n\tName                    string `json:\"name\"`                       // e.g. Linux\n\tArch                    string `json:\"arch\"`                       // e.g. amd64\n\tVersion                 string `json:\"version\"`                    // e.g. 4.9.87-linuxkit-aufs\n\tAvailableProcessors     int    `json:\"available_processors\"`       // e.g. 4\n\tAllocatedProcessors     int    `json:\"allocated_processors\"`       // e.g. 4\n}\n\n// NodesInfoNodeProcess represents process-related information.\ntype NodesInfoNodeProcess struct {\n\tRefreshInterval         string `json:\"refresh_interval\"`           // e.g. 1s\n\tRefreshIntervalInMillis int64  `json:\"refresh_interval_in_millis\"` // e.g. 1000\n\tID                      int    `json:\"id\"`                         // process id, e.g. 87079\n\tMlockall                bool   `json:\"mlockall\"`                   // e.g. false\n}\n\n// NodesInfoNodeJVM represents JVM-related information.\ntype NodesInfoNodeJVM struct {\n\tPID               int       `json:\"pid\"`                  // process id, e.g. 87079\n\tVersion           string    `json:\"version\"`              // e.g. \"1.8.0_161\"\n\tVMName            string    `json:\"vm_name\"`              // e.g. \"OpenJDK 64-Bit Server VM\"\n\tVMVersion         string    `json:\"vm_version\"`           // e.g. \"25.161-b14\"\n\tVMVendor          string    `json:\"vm_vendor\"`            // e.g. \"Oracle Corporation\"\n\tStartTime         time.Time `json:\"start_time\"`           // e.g. \"2018-03-30T11:06:36.644Z\"\n\tStartTimeInMillis int64     `json:\"start_time_in_millis\"` // e.g. 1522407996644\n\n\t// Mem information\n\tMem struct {\n\t\tHeapInit           string `json:\"heap_init\"`              // e.g. \"1gb\"\n\t\tHeapInitInBytes    int    `json:\"heap_init_in_bytes\"`     // e.g. 1073741824\n\t\tHeapMax            string `json:\"heap_max\"`               // e.g. \"1007.3mb\"\n\t\tHeapMaxInBytes     int    `json:\"heap_max_in_bytes\"`      // e.g. 1056309248\n\t\tNonHeapInit        string `json:\"non_heap_init\"`          // e.g. \"2.4mb\"\n\t\tNonHeapInitInBytes int    `json:\"non_heap_init_in_bytes\"` // e.g. 2555904\n\t\tNonHeapMax         string `json:\"non_heap_max\"`           // e.g. \"0b\"\n\t\tNonHeapMaxInBytes  int    `json:\"non_heap_max_in_bytes\"`  // e.g. 0\n\t\tDirectMax          string `json:\"direct_max\"`             // e.g. \"1007.3mb\"\n\t\tDirectMaxInBytes   int    `json:\"direct_max_in_bytes\"`    // e.g. 1056309248\n\t} `json:\"mem\"`\n\n\tGCCollectors []string `json:\"gc_collectors\"` // e.g. [\"ParNew\", \"ConcurrentMarkSweep\"]\n\tMemoryPools  []string `json:\"memory_pools\"`  // e.g. [\"Code Cache\", \"Metaspace\", \"Compressed Class Space\", \"Par Eden Space\", \"Par Survivor Space\", \"CMS Old Gen\"]\n\n\t// UsingCompressedOrdinaryObjectPointers should be a bool, but is a\n\t// string in 6.2.3. We use an interface{} for now so that it won't break\n\t// when this will be fixed in later versions of Elasticsearch.\n\tUsingCompressedOrdinaryObjectPointers interface{} `json:\"using_compressed_ordinary_object_pointers\"`\n\n\tInputArguments []string `json:\"input_arguments\"` // e.g. [\"-Xms1g\", \"-Xmx1g\" ...]\n}\n\n// NodesInfoNodeThreadPool represents information about the thread pool.\ntype NodesInfoNodeThreadPool struct {\n\tForceMerge        *NodesInfoNodeThreadPoolSection `json:\"force_merge\"`\n\tFetchShardStarted *NodesInfoNodeThreadPoolSection `json:\"fetch_shard_started\"`\n\tListener          *NodesInfoNodeThreadPoolSection `json:\"listener\"`\n\tIndex             *NodesInfoNodeThreadPoolSection `json:\"index\"`\n\tRefresh           *NodesInfoNodeThreadPoolSection `json:\"refresh\"`\n\tGeneric           *NodesInfoNodeThreadPoolSection `json:\"generic\"`\n\tWarmer            *NodesInfoNodeThreadPoolSection `json:\"warmer\"`\n\tSearch            *NodesInfoNodeThreadPoolSection `json:\"search\"`\n\tFlush             *NodesInfoNodeThreadPoolSection `json:\"flush\"`\n\tFetchShardStore   *NodesInfoNodeThreadPoolSection `json:\"fetch_shard_store\"`\n\tManagement        *NodesInfoNodeThreadPoolSection `json:\"management\"`\n\tGet               *NodesInfoNodeThreadPoolSection `json:\"get\"`\n\tBulk              *NodesInfoNodeThreadPoolSection `json:\"bulk\"`\n\tSnapshot          *NodesInfoNodeThreadPoolSection `json:\"snapshot\"`\n\n\tPercolate *NodesInfoNodeThreadPoolSection `json:\"percolate\"` // check\n\tBench     *NodesInfoNodeThreadPoolSection `json:\"bench\"`     // check\n\tSuggest   *NodesInfoNodeThreadPoolSection `json:\"suggest\"`   // deprecated\n\tOptimize  *NodesInfoNodeThreadPoolSection `json:\"optimize\"`  // deprecated\n\tMerge     *NodesInfoNodeThreadPoolSection `json:\"merge\"`     // deprecated\n}\n\n// NodesInfoNodeThreadPoolSection represents information about a certain\n// type of thread pool, e.g. for indexing or searching.\ntype NodesInfoNodeThreadPoolSection struct {\n\tType      string      `json:\"type\"`       // e.g. fixed, scaling, or fixed_auto_queue_size\n\tMin       int         `json:\"min\"`        // e.g. 4\n\tMax       int         `json:\"max\"`        // e.g. 4\n\tKeepAlive string      `json:\"keep_alive\"` // e.g. \"5m\"\n\tQueueSize interface{} `json:\"queue_size\"` // e.g. \"1k\" or -1\n}\n\n// NodesInfoNodeTransport represents transport-related information.\ntype NodesInfoNodeTransport struct {\n\tBoundAddress   []string                                  `json:\"bound_address\"`\n\tPublishAddress string                                    `json:\"publish_address\"`\n\tProfiles       map[string]*NodesInfoNodeTransportProfile `json:\"profiles\"`\n}\n\n// NodesInfoNodeTransportProfile represents a transport profile.\ntype NodesInfoNodeTransportProfile struct {\n\tBoundAddress   []string `json:\"bound_address\"`\n\tPublishAddress string   `json:\"publish_address\"`\n}\n\n// NodesInfoNodeHTTP represents HTTP-related information.\ntype NodesInfoNodeHTTP struct {\n\tBoundAddress            []string `json:\"bound_address\"`      // e.g. [\"127.0.0.1:9200\", \"[fe80::1]:9200\", \"[::1]:9200\"]\n\tPublishAddress          string   `json:\"publish_address\"`    // e.g. \"127.0.0.1:9300\"\n\tMaxContentLength        string   `json:\"max_content_length\"` // e.g. \"100mb\"\n\tMaxContentLengthInBytes int64    `json:\"max_content_length_in_bytes\"`\n}\n\n// NodesInfoNodePlugin represents information about a plugin.\ntype NodesInfoNodePlugin struct {\n\tName                 string   `json:\"name\"`    // e.g. \"ingest-geoip\"\n\tVersion              string   `json:\"version\"` // e.g. \"6.2.3\"\n\tElasticsearchVersion string   `json:\"elasticsearch_version\"`\n\tJavaVersion          string   `json:\"java_version\"`\n\tDescription          string   `json:\"description\"` // e.g. \"Ingest processor ...\"\n\tClassname            string   `json:\"classname\"`   // e.g. \"org.elasticsearch.ingest.geoip.IngestGeoIpPlugin\"\n\tExtendedPlugins      []string `json:\"extended_plugins\"`\n\tHasNativeController  bool     `json:\"has_native_controller\"`\n\tRequiresKeystore     bool     `json:\"requires_keystore\"`\n}\n\n// NodesInfoNodeModule represents information about a module.\ntype NodesInfoNodeModule struct {\n\tName                 string   `json:\"name\"`    // e.g. \"ingest-geoip\"\n\tVersion              string   `json:\"version\"` // e.g. \"6.2.3\"\n\tElasticsearchVersion string   `json:\"elasticsearch_version\"`\n\tJavaVersion          string   `json:\"java_version\"`\n\tDescription          string   `json:\"description\"` // e.g. \"Ingest processor ...\"\n\tClassname            string   `json:\"classname\"`   // e.g. \"org.elasticsearch.ingest.geoip.IngestGeoIpPlugin\"\n\tExtendedPlugins      []string `json:\"extended_plugins\"`\n\tHasNativeController  bool     `json:\"has_native_controller\"`\n\tRequiresKeystore     bool     `json:\"requires_keystore\"`\n}\n\n// NodesInfoNodeIngest represents information about the ingester.\ntype NodesInfoNodeIngest struct {\n\tProcessors []*NodesInfoNodeIngestProcessorInfo `json:\"processors\"`\n}\n\n// NodesInfoNodeIngestProcessorInfo represents ingest processor info.\ntype NodesInfoNodeIngestProcessorInfo struct {\n\tType string `json:\"type\"` // e.g. append, convert, date etc.\n}\n"
  },
  {
    "path": "nodes_info_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestNodesInfoBuildURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tNodeIDs  []string\n\t\tMetrics  []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\tnil,\n\t\t\tnil,\n\t\t\t\"/_nodes/_all/_all\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"/_nodes/_all/_all\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"node1\"},\n\t\t\t[]string{},\n\t\t\t\"/_nodes/node1/_all\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"node1\", \"node2\"},\n\t\t\tnil,\n\t\t\t\"/_nodes/node1%2Cnode2/_all\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"node1\", \"node2\"},\n\t\t\t[]string{\"metric1\", \"metric2\"},\n\t\t\t\"/_nodes/node1%2Cnode2/metric1%2Cmetric2\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.NodesInfo().NodeId(test.NodeIDs...).Metric(test.Metrics...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"case #%d: %v\", i+1, err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\nfunc TestNodesInfo(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tinfo, err := client.NodesInfo().Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif info == nil {\n\t\tt.Fatal(\"expected nodes info\")\n\t}\n\n\tif info.ClusterName == \"\" {\n\t\tt.Errorf(\"expected cluster name; got: %q\", info.ClusterName)\n\t}\n\tif len(info.Nodes) == 0 {\n\t\tt.Errorf(\"expected some nodes; got: %d\", len(info.Nodes))\n\t}\n\tfor id, node := range info.Nodes {\n\t\tif id == \"\" {\n\t\t\tt.Errorf(\"expected node id; got: %q\", id)\n\t\t}\n\t\tif node == nil {\n\t\t\tt.Fatalf(\"expected node info; got: %v\", node)\n\t\t}\n\t\tif node.IP == \"\" {\n\t\t\tt.Errorf(\"expected node IP; got: %q\", node.IP)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "nodes_stats.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// NodesStatsService returns node statistics.\n// See http://www.elastic.co/guide/en/elasticsearch/reference/7.0/cluster-nodes-stats.html\n// for details.\ntype NodesStatsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tmetric           []string\n\tindexMetric      []string\n\tnodeId           []string\n\tcompletionFields []string\n\tfielddataFields  []string\n\tfields           []string\n\tgroups           *bool\n\tlevel            string\n\ttimeout          string\n\ttypes            []string\n}\n\n// NewNodesStatsService creates a new NodesStatsService.\nfunc NewNodesStatsService(client *Client) *NodesStatsService {\n\treturn &NodesStatsService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *NodesStatsService) Pretty(pretty bool) *NodesStatsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *NodesStatsService) Human(human bool) *NodesStatsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *NodesStatsService) ErrorTrace(errorTrace bool) *NodesStatsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *NodesStatsService) FilterPath(filterPath ...string) *NodesStatsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *NodesStatsService) Header(name string, value string) *NodesStatsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *NodesStatsService) Headers(headers http.Header) *NodesStatsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Metric limits the information returned to the specified metrics.\nfunc (s *NodesStatsService) Metric(metric ...string) *NodesStatsService {\n\ts.metric = append(s.metric, metric...)\n\treturn s\n}\n\n// IndexMetric limits the information returned for `indices` metric\n// to the specific index metrics. Isn't used if `indices` (or `all`)\n// metric isn't specified..\nfunc (s *NodesStatsService) IndexMetric(indexMetric ...string) *NodesStatsService {\n\ts.indexMetric = append(s.indexMetric, indexMetric...)\n\treturn s\n}\n\n// NodeId is a list of node IDs or names to limit the returned information;\n// use `_local` to return information from the node you're connecting to,\n// leave empty to get information from all nodes.\nfunc (s *NodesStatsService) NodeId(nodeId ...string) *NodesStatsService {\n\ts.nodeId = append(s.nodeId, nodeId...)\n\treturn s\n}\n\n// CompletionFields is a list of fields for `fielddata` and `suggest`\n// index metric (supports wildcards).\nfunc (s *NodesStatsService) CompletionFields(completionFields ...string) *NodesStatsService {\n\ts.completionFields = append(s.completionFields, completionFields...)\n\treturn s\n}\n\n// FielddataFields is a list of fields for `fielddata` index metric (supports wildcards).\nfunc (s *NodesStatsService) FielddataFields(fielddataFields ...string) *NodesStatsService {\n\ts.fielddataFields = append(s.fielddataFields, fielddataFields...)\n\treturn s\n}\n\n// Fields is a list of fields for `fielddata` and `completion` index metric (supports wildcards).\nfunc (s *NodesStatsService) Fields(fields ...string) *NodesStatsService {\n\ts.fields = append(s.fields, fields...)\n\treturn s\n}\n\n// Groups is a list of search groups for `search` index metric.\nfunc (s *NodesStatsService) Groups(groups bool) *NodesStatsService {\n\ts.groups = &groups\n\treturn s\n}\n\n// Level specifies whether to return indices stats aggregated at node, index or shard level.\nfunc (s *NodesStatsService) Level(level string) *NodesStatsService {\n\ts.level = level\n\treturn s\n}\n\n// Timeout specifies an explicit operation timeout.\nfunc (s *NodesStatsService) Timeout(timeout string) *NodesStatsService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// Types a list of document types for the `indexing` index metric.\nfunc (s *NodesStatsService) Types(types ...string) *NodesStatsService {\n\ts.types = append(s.types, types...)\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *NodesStatsService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\tif len(s.nodeId) > 0 && len(s.metric) > 0 && len(s.indexMetric) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_nodes/{node_id}/stats/{metric}/{index_metric}\", map[string]string{\n\t\t\t\"index_metric\": strings.Join(s.indexMetric, \",\"),\n\t\t\t\"node_id\":      strings.Join(s.nodeId, \",\"),\n\t\t\t\"metric\":       strings.Join(s.metric, \",\"),\n\t\t})\n\t} else if len(s.nodeId) > 0 && len(s.metric) > 0 && len(s.indexMetric) == 0 {\n\t\tpath, err = uritemplates.Expand(\"/_nodes/{node_id}/stats/{metric}\", map[string]string{\n\t\t\t\"node_id\": strings.Join(s.nodeId, \",\"),\n\t\t\t\"metric\":  strings.Join(s.metric, \",\"),\n\t\t})\n\t} else if len(s.nodeId) > 0 && len(s.metric) == 0 && len(s.indexMetric) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_nodes/{node_id}/stats/_all/{index_metric}\", map[string]string{\n\t\t\t\"index_metric\": strings.Join(s.indexMetric, \",\"),\n\t\t\t\"node_id\":      strings.Join(s.nodeId, \",\"),\n\t\t})\n\t} else if len(s.nodeId) > 0 && len(s.metric) == 0 && len(s.indexMetric) == 0 {\n\t\tpath, err = uritemplates.Expand(\"/_nodes/{node_id}/stats\", map[string]string{\n\t\t\t\"node_id\": strings.Join(s.nodeId, \",\"),\n\t\t})\n\t} else if len(s.nodeId) == 0 && len(s.metric) > 0 && len(s.indexMetric) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_nodes/stats/{metric}/{index_metric}\", map[string]string{\n\t\t\t\"index_metric\": strings.Join(s.indexMetric, \",\"),\n\t\t\t\"metric\":       strings.Join(s.metric, \",\"),\n\t\t})\n\t} else if len(s.nodeId) == 0 && len(s.metric) > 0 && len(s.indexMetric) == 0 {\n\t\tpath, err = uritemplates.Expand(\"/_nodes/stats/{metric}\", map[string]string{\n\t\t\t\"metric\": strings.Join(s.metric, \",\"),\n\t\t})\n\t} else if len(s.nodeId) == 0 && len(s.metric) == 0 && len(s.indexMetric) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_nodes/stats/_all/{index_metric}\", map[string]string{\n\t\t\t\"index_metric\": strings.Join(s.indexMetric, \",\"),\n\t\t})\n\t} else { // if len(s.nodeId) == 0 && len(s.metric) == 0 && len(s.indexMetric) == 0 {\n\t\tpath = \"/_nodes/stats\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif len(s.completionFields) > 0 {\n\t\tparams.Set(\"completion_fields\", strings.Join(s.completionFields, \",\"))\n\t}\n\tif len(s.fielddataFields) > 0 {\n\t\tparams.Set(\"fielddata_fields\", strings.Join(s.fielddataFields, \",\"))\n\t}\n\tif len(s.fields) > 0 {\n\t\tparams.Set(\"fields\", strings.Join(s.fields, \",\"))\n\t}\n\tif s.groups != nil {\n\t\tparams.Set(\"groups\", fmt.Sprintf(\"%v\", *s.groups))\n\t}\n\tif s.level != \"\" {\n\t\tparams.Set(\"level\", s.level)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif len(s.types) > 0 {\n\t\tparams.Set(\"types\", strings.Join(s.types, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *NodesStatsService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *NodesStatsService) Do(ctx context.Context) (*NodesStatsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(NodesStatsResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// NodesStatsResponse is the response of NodesStatsService.Do.\ntype NodesStatsResponse struct {\n\tClusterName string                     `json:\"cluster_name\"`\n\tNodes       map[string]*NodesStatsNode `json:\"nodes\"`\n}\n\ntype NodesStatsNode struct {\n\t// Timestamp when these stats we're gathered.\n\tTimestamp int64 `json:\"timestamp\"`\n\t// Name of the node, e.g. \"Mister Fear\"\n\tName string `json:\"name\"`\n\t// TransportAddress, e.g. \"127.0.0.1:9300\"\n\tTransportAddress string `json:\"transport_address\"`\n\t// Host is the host name, e.g. \"macbookair\"\n\tHost string `json:\"host\"`\n\t// IP is an IP address, e.g. \"192.168.1.2\"\n\tIP string `json:\"ip\"`\n\t// Roles is a list of the roles of the node, e.g. master, data, ingest.\n\tRoles []string `json:\"roles\"`\n\n\t// Attributes of the node.\n\tAttributes map[string]interface{} `json:\"attributes\"`\n\n\t// Indices returns index information.\n\tIndices *NodesStatsIndex `json:\"indices\"`\n\n\t// OS information, e.g. CPU and memory.\n\tOS *NodesStatsNodeOS `json:\"os\"`\n\n\t// Process information, e.g. max file descriptors.\n\tProcess *NodesStatsNodeProcess `json:\"process\"`\n\n\t// JVM information, e.g. VM version.\n\tJVM *NodesStatsNodeJVM `json:\"jvm\"`\n\n\t// ThreadPool information.\n\tThreadPool map[string]*NodesStatsNodeThreadPool `json:\"thread_pool\"`\n\n\t// FS returns information about the filesystem.\n\tFS *NodesStatsNodeFS `json:\"fs\"`\n\n\t// Network information.\n\tTransport *NodesStatsNodeTransport `json:\"transport\"`\n\n\t// HTTP information.\n\tHTTP *NodesStatsNodeHTTP `json:\"http\"`\n\n\t// Breaker contains information about circuit breakers.\n\tBreaker map[string]*NodesStatsBreaker `json:\"breakers\"`\n\n\t// ScriptStats information.\n\tScriptStats *NodesStatsScriptStats `json:\"script\"`\n\n\t// Discovery information.\n\tDiscovery *NodesStatsDiscovery `json:\"discovery\"`\n\n\t// Ingest information\n\tIngest *NodesStatsIngest `json:\"ingest\"`\n}\n\ntype NodesStatsIndex struct {\n\tDocs         *NodesStatsDocsStats         `json:\"docs\"`\n\tShards       *NodesStatsShardCountStats   `json:\"shards_stats\"`\n\tStore        *NodesStatsStoreStats        `json:\"store\"`\n\tIndexing     *NodesStatsIndexingStats     `json:\"indexing\"`\n\tGet          *NodesStatsGetStats          `json:\"get\"`\n\tSearch       *NodesStatsSearchStats       `json:\"search\"`\n\tMerges       *NodesStatsMergeStats        `json:\"merges\"`\n\tRefresh      *NodesStatsRefreshStats      `json:\"refresh\"`\n\tFlush        *NodesStatsFlushStats        `json:\"flush\"`\n\tWarmer       *NodesStatsWarmerStats       `json:\"warmer\"`\n\tQueryCache   *NodesStatsQueryCacheStats   `json:\"query_cache\"`\n\tFielddata    *NodesStatsFielddataStats    `json:\"fielddata\"`\n\tCompletion   *NodesStatsCompletionStats   `json:\"completion\"`\n\tSegments     *NodesStatsSegmentsStats     `json:\"segments\"`\n\tTranslog     *NodesStatsTranslogStats     `json:\"translog\"`\n\tRequestCache *NodesStatsRequestCacheStats `json:\"request_cache\"`\n\tRecovery     NodesStatsRecoveryStats      `json:\"recovery\"`\n\n\tIndicesLevel map[string]*NodesStatsIndex `json:\"indices\"` // for level=indices\n\tShardsLevel  map[string]*NodesStatsIndex `json:\"shards\"`  // for level=shards\n}\n\ntype NodesStatsDocsStats struct {\n\tCount   int64 `json:\"count\"`\n\tDeleted int64 `json:\"deleted\"`\n}\n\ntype NodesStatsShardCountStats struct {\n\tTotalCount int64 `json:\"total_count\"`\n}\n\ntype NodesStatsStoreStats struct {\n\tSize        string `json:\"size\"`\n\tSizeInBytes int64  `json:\"size_in_bytes\"`\n}\n\ntype NodesStatsIndexingStats struct {\n\tIndexTotal            int64  `json:\"index_total\"`\n\tIndexTime             string `json:\"index_time\"`\n\tIndexTimeInMillis     int64  `json:\"index_time_in_millis\"`\n\tIndexCurrent          int64  `json:\"index_current\"`\n\tIndexFailed           int64  `json:\"index_failed\"`\n\tDeleteTotal           int64  `json:\"delete_total\"`\n\tDeleteTime            string `json:\"delete_time\"`\n\tDeleteTimeInMillis    int64  `json:\"delete_time_in_millis\"`\n\tDeleteCurrent         int64  `json:\"delete_current\"`\n\tNoopUpdateTotal       int64  `json:\"noop_update_total\"`\n\tIsThrottled           bool   `json:\"is_throttled\"`\n\tThrottledTime         string `json:\"throttle_time\"` // no typo, see https://github.com/elastic/elasticsearch/blob/ff99bc1d3f8a7ea72718872d214ec2097dfca276/server/src/main/java/org/elasticsearch/index/shard/IndexingStats.java#L244\n\tThrottledTimeInMillis int64  `json:\"throttle_time_in_millis\"`\n\n\tTypes map[string]*NodesStatsIndexingStats `json:\"types\"` // stats for individual types\n}\n\ntype NodesStatsGetStats struct {\n\tTotal               int64  `json:\"total\"`\n\tTime                string `json:\"get_time\"`\n\tTimeInMillis        int64  `json:\"time_in_millis\"`\n\tExists              int64  `json:\"exists\"`\n\tExistsTime          string `json:\"exists_time\"`\n\tExistsTimeInMillis  int64  `json:\"exists_in_millis\"`\n\tMissing             int64  `json:\"missing\"`\n\tMissingTime         string `json:\"missing_time\"`\n\tMissingTimeInMillis int64  `json:\"missing_in_millis\"`\n\tCurrent             int64  `json:\"current\"`\n}\n\ntype NodesStatsSearchStats struct {\n\tOpenContexts       int64  `json:\"open_contexts\"`\n\tQueryTotal         int64  `json:\"query_total\"`\n\tQueryTime          string `json:\"query_time\"`\n\tQueryTimeInMillis  int64  `json:\"query_time_in_millis\"`\n\tQueryCurrent       int64  `json:\"query_current\"`\n\tFetchTotal         int64  `json:\"fetch_total\"`\n\tFetchTime          string `json:\"fetch_time\"`\n\tFetchTimeInMillis  int64  `json:\"fetch_time_in_millis\"`\n\tFetchCurrent       int64  `json:\"fetch_current\"`\n\tScrollTotal        int64  `json:\"scroll_total\"`\n\tScrollTime         string `json:\"scroll_time\"`\n\tScrollTimeInMillis int64  `json:\"scroll_time_in_millis\"`\n\tScrollCurrent      int64  `json:\"scroll_current\"`\n\n\tGroups map[string]*NodesStatsSearchStats `json:\"groups\"` // stats for individual groups\n}\n\ntype NodesStatsMergeStats struct {\n\tCurrent                    int64  `json:\"current\"`\n\tCurrentDocs                int64  `json:\"current_docs\"`\n\tCurrentSize                string `json:\"current_size\"`\n\tCurrentSizeInBytes         int64  `json:\"current_size_in_bytes\"`\n\tTotal                      int64  `json:\"total\"`\n\tTotalTime                  string `json:\"total_time\"`\n\tTotalTimeInMillis          int64  `json:\"total_time_in_millis\"`\n\tTotalDocs                  int64  `json:\"total_docs\"`\n\tTotalSize                  string `json:\"total_size\"`\n\tTotalSizeInBytes           int64  `json:\"total_size_in_bytes\"`\n\tTotalStoppedTime           string `json:\"total_stopped_time\"`\n\tTotalStoppedTimeInMillis   int64  `json:\"total_stopped_time_in_millis\"`\n\tTotalThrottledTime         string `json:\"total_throttled_time\"`\n\tTotalThrottledTimeInMillis int64  `json:\"total_throttled_time_in_millis\"`\n\tTotalThrottleBytes         string `json:\"total_auto_throttle\"`\n\tTotalThrottleBytesInBytes  int64  `json:\"total_auto_throttle_in_bytes\"`\n}\n\ntype NodesStatsRefreshStats struct {\n\tTotal             int64  `json:\"total\"`\n\tTotalTime         string `json:\"total_time\"`\n\tTotalTimeInMillis int64  `json:\"total_time_in_millis\"`\n}\n\ntype NodesStatsFlushStats struct {\n\tTotal             int64  `json:\"total\"`\n\tTotalTime         string `json:\"total_time\"`\n\tTotalTimeInMillis int64  `json:\"total_time_in_millis\"`\n}\n\ntype NodesStatsWarmerStats struct {\n\tCurrent           int64  `json:\"current\"`\n\tTotal             int64  `json:\"total\"`\n\tTotalTime         string `json:\"total_time\"`\n\tTotalTimeInMillis int64  `json:\"total_time_in_millis\"`\n}\n\ntype NodesStatsQueryCacheStats struct {\n\tMemorySize        string `json:\"memory_size\"`\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes\"`\n\tTotalCount        int64  `json:\"total_count\"`\n\tHitCount          int64  `json:\"hit_count\"`\n\tMissCount         int64  `json:\"miss_count\"`\n\tCacheSize         int64  `json:\"cache_size\"`\n\tCacheCount        int64  `json:\"cache_count\"`\n\tEvictions         int64  `json:\"evictions\"`\n}\n\ntype NodesStatsFielddataStats struct {\n\tMemorySize        string `json:\"memory_size\"`\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes\"`\n\tEvictions         int64  `json:\"evictions\"`\n\tFields            map[string]struct {\n\t\tMemorySize        string `json:\"memory_size\"`\n\t\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes\"`\n\t} `json:\"fields\"`\n}\n\ntype NodesStatsCompletionStats struct {\n\tSize        string `json:\"size\"`\n\tSizeInBytes int64  `json:\"size_in_bytes\"`\n\tFields      map[string]struct {\n\t\tSize        string `json:\"size\"`\n\t\tSizeInBytes int64  `json:\"size_in_bytes\"`\n\t} `json:\"fields\"`\n}\n\ntype NodesStatsSegmentsStats struct {\n\tCount                       int64  `json:\"count\"`\n\tMemory                      string `json:\"memory\"`\n\tMemoryInBytes               int64  `json:\"memory_in_bytes\"`\n\tTermsMemory                 string `json:\"terms_memory\"`\n\tTermsMemoryInBytes          int64  `json:\"terms_memory_in_bytes\"`\n\tStoredFieldsMemory          string `json:\"stored_fields_memory\"`\n\tStoredFieldsMemoryInBytes   int64  `json:\"stored_fields_memory_in_bytes\"`\n\tTermVectorsMemory           string `json:\"term_vectors_memory\"`\n\tTermVectorsMemoryInBytes    int64  `json:\"term_vectors_memory_in_bytes\"`\n\tNormsMemory                 string `json:\"norms_memory\"`\n\tNormsMemoryInBytes          int64  `json:\"norms_memory_in_bytes\"`\n\tDocValuesMemory             string `json:\"doc_values_memory\"`\n\tDocValuesMemoryInBytes      int64  `json:\"doc_values_memory_in_bytes\"`\n\tIndexWriterMemory           string `json:\"index_writer_memory\"`\n\tIndexWriterMemoryInBytes    int64  `json:\"index_writer_memory_in_bytes\"`\n\tIndexWriterMaxMemory        string `json:\"index_writer_max_memory\"`\n\tIndexWriterMaxMemoryInBytes int64  `json:\"index_writer_max_memory_in_bytes\"`\n\tVersionMapMemory            string `json:\"version_map_memory\"`\n\tVersionMapMemoryInBytes     int64  `json:\"version_map_memory_in_bytes\"`\n\tFixedBitSetMemory           string `json:\"fixed_bit_set\"` // not a typo\n\tFixedBitSetMemoryInBytes    int64  `json:\"fixed_bit_set_memory_in_bytes\"`\n}\n\ntype NodesStatsTranslogStats struct {\n\tOperations  int64  `json:\"operations\"`\n\tSize        string `json:\"size\"`\n\tSizeInBytes int64  `json:\"size_in_bytes\"`\n}\n\ntype NodesStatsRequestCacheStats struct {\n\tMemorySize        string `json:\"memory_size\"`\n\tMemorySizeInBytes int64  `json:\"memory_size_in_bytes\"`\n\tEvictions         int64  `json:\"evictions\"`\n\tHitCount          int64  `json:\"hit_count\"`\n\tMissCount         int64  `json:\"miss_count\"`\n}\n\ntype NodesStatsRecoveryStats struct {\n\tCurrentAsSource int `json:\"current_as_source\"`\n\tCurrentAsTarget int `json:\"current_as_target\"`\n}\n\ntype NodesStatsNodeOS struct {\n\tTimestamp int64                 `json:\"timestamp\"`\n\tCPU       *NodesStatsNodeOSCPU  `json:\"cpu\"`\n\tMem       *NodesStatsNodeOSMem  `json:\"mem\"`\n\tSwap      *NodesStatsNodeOSSwap `json:\"swap\"`\n}\n\ntype NodesStatsNodeOSCPU struct {\n\tPercent     int                `json:\"percent\"`\n\tLoadAverage map[string]float64 `json:\"load_average\"` // keys are: 1m, 5m, and 15m\n}\n\ntype NodesStatsNodeOSMem struct {\n\tTotal        string `json:\"total\"`\n\tTotalInBytes int64  `json:\"total_in_bytes\"`\n\tFree         string `json:\"free\"`\n\tFreeInBytes  int64  `json:\"free_in_bytes\"`\n\tUsed         string `json:\"used\"`\n\tUsedInBytes  int64  `json:\"used_in_bytes\"`\n\tFreePercent  int    `json:\"free_percent\"`\n\tUsedPercent  int    `json:\"used_percent\"`\n}\n\ntype NodesStatsNodeOSSwap struct {\n\tTotal        string `json:\"total\"`\n\tTotalInBytes int64  `json:\"total_in_bytes\"`\n\tFree         string `json:\"free\"`\n\tFreeInBytes  int64  `json:\"free_in_bytes\"`\n\tUsed         string `json:\"used\"`\n\tUsedInBytes  int64  `json:\"used_in_bytes\"`\n}\n\ntype NodesStatsNodeProcess struct {\n\tTimestamp           int64 `json:\"timestamp\"`\n\tOpenFileDescriptors int64 `json:\"open_file_descriptors\"`\n\tMaxFileDescriptors  int64 `json:\"max_file_descriptors\"`\n\tCPU                 struct {\n\t\tPercent       int    `json:\"percent\"`\n\t\tTotal         string `json:\"total\"`\n\t\tTotalInMillis int64  `json:\"total_in_millis\"`\n\t} `json:\"cpu\"`\n\tMem struct {\n\t\tTotalVirtual        string `json:\"total_virtual\"`\n\t\tTotalVirtualInBytes int64  `json:\"total_virtual_in_bytes\"`\n\t} `json:\"mem\"`\n}\n\ntype NodesStatsNodeJVM struct {\n\tTimestamp      int64                                   `json:\"timestamp\"`\n\tUptime         string                                  `json:\"uptime\"`\n\tUptimeInMillis int64                                   `json:\"uptime_in_millis\"`\n\tMem            *NodesStatsNodeJVMMem                   `json:\"mem\"`\n\tThreads        *NodesStatsNodeJVMThreads               `json:\"threads\"`\n\tGC             *NodesStatsNodeJVMGC                    `json:\"gc\"`\n\tBufferPools    map[string]*NodesStatsNodeJVMBufferPool `json:\"buffer_pools\"`\n\tClasses        *NodesStatsNodeJVMClasses               `json:\"classes\"`\n}\n\ntype NodesStatsNodeJVMMem struct {\n\tHeapUsed                string `json:\"heap_used\"`\n\tHeapUsedInBytes         int64  `json:\"heap_used_in_bytes\"`\n\tHeapUsedPercent         int    `json:\"heap_used_percent\"`\n\tHeapCommitted           string `json:\"heap_committed\"`\n\tHeapCommittedInBytes    int64  `json:\"heap_committed_in_bytes\"`\n\tHeapMax                 string `json:\"heap_max\"`\n\tHeapMaxInBytes          int64  `json:\"heap_max_in_bytes\"`\n\tNonHeapUsed             string `json:\"non_heap_used\"`\n\tNonHeapUsedInBytes      int64  `json:\"non_heap_used_in_bytes\"`\n\tNonHeapCommitted        string `json:\"non_heap_committed\"`\n\tNonHeapCommittedInBytes int64  `json:\"non_heap_committed_in_bytes\"`\n\tPools                   map[string]struct {\n\t\tUsed            string `json:\"used\"`\n\t\tUsedInBytes     int64  `json:\"used_in_bytes\"`\n\t\tMax             string `json:\"max\"`\n\t\tMaxInBytes      int64  `json:\"max_in_bytes\"`\n\t\tPeakUsed        string `json:\"peak_used\"`\n\t\tPeakUsedInBytes int64  `json:\"peak_used_in_bytes\"`\n\t\tPeakMax         string `json:\"peak_max\"`\n\t\tPeakMaxInBytes  int64  `json:\"peak_max_in_bytes\"`\n\t} `json:\"pools\"`\n}\n\ntype NodesStatsNodeJVMThreads struct {\n\tCount     int64 `json:\"count\"`\n\tPeakCount int64 `json:\"peak_count\"`\n}\n\ntype NodesStatsNodeJVMGC struct {\n\tCollectors map[string]*NodesStatsNodeJVMGCCollector `json:\"collectors\"`\n}\n\ntype NodesStatsNodeJVMGCCollector struct {\n\tCollectionCount        int64  `json:\"collection_count\"`\n\tCollectionTime         string `json:\"collection_time\"`\n\tCollectionTimeInMillis int64  `json:\"collection_time_in_millis\"`\n}\n\ntype NodesStatsNodeJVMBufferPool struct {\n\tCount                int64  `json:\"count\"`\n\tTotalCapacity        string `json:\"total_capacity\"`\n\tTotalCapacityInBytes int64  `json:\"total_capacity_in_bytes\"`\n}\n\ntype NodesStatsNodeJVMClasses struct {\n\tCurrentLoadedCount int64 `json:\"current_loaded_count\"`\n\tTotalLoadedCount   int64 `json:\"total_loaded_count\"`\n\tTotalUnloadedCount int64 `json:\"total_unloaded_count\"`\n}\n\ntype NodesStatsNodeThreadPool struct {\n\tThreads   int   `json:\"threads\"`\n\tQueue     int   `json:\"queue\"`\n\tActive    int   `json:\"active\"`\n\tRejected  int64 `json:\"rejected\"`\n\tLargest   int   `json:\"largest\"`\n\tCompleted int64 `json:\"completed\"`\n}\n\ntype NodesStatsNodeFS struct {\n\tTimestamp int64                    `json:\"timestamp\"`\n\tTotal     *NodesStatsNodeFSEntry   `json:\"total\"`\n\tData      []*NodesStatsNodeFSEntry `json:\"data\"`\n\tIOStats   *NodesStatsNodeFSIOStats `json:\"io_stats\"`\n}\n\ntype NodesStatsNodeFSEntry struct {\n\tPath             string `json:\"path\"`\n\tMount            string `json:\"mount\"`\n\tType             string `json:\"type\"`\n\tTotal            string `json:\"total\"`\n\tTotalInBytes     int64  `json:\"total_in_bytes\"`\n\tFree             string `json:\"free\"`\n\tFreeInBytes      int64  `json:\"free_in_bytes\"`\n\tAvailable        string `json:\"available\"`\n\tAvailableInBytes int64  `json:\"available_in_bytes\"`\n\tSpins            string `json:\"spins\"`\n}\n\ntype NodesStatsNodeFSIOStats struct {\n\tDevices []*NodesStatsNodeFSIOStatsEntry `json:\"devices\"`\n\tTotal   *NodesStatsNodeFSIOStatsEntry   `json:\"total\"`\n}\n\ntype NodesStatsNodeFSIOStatsEntry struct {\n\tDeviceName      string `json:\"device_name\"`\n\tOperations      int64  `json:\"operations\"`\n\tReadOperations  int64  `json:\"read_operations\"`\n\tWriteOperations int64  `json:\"write_operations\"`\n\tReadKilobytes   int64  `json:\"read_kilobytes\"`\n\tWriteKilobytes  int64  `json:\"write_kilobytes\"`\n}\n\ntype NodesStatsNodeTransport struct {\n\tServerOpen    int    `json:\"server_open\"`\n\tRxCount       int64  `json:\"rx_count\"`\n\tRxSize        string `json:\"rx_size\"`\n\tRxSizeInBytes int64  `json:\"rx_size_in_bytes\"`\n\tTxCount       int64  `json:\"tx_count\"`\n\tTxSize        string `json:\"tx_size\"`\n\tTxSizeInBytes int64  `json:\"tx_size_in_bytes\"`\n}\n\ntype NodesStatsNodeHTTP struct {\n\tCurrentOpen int `json:\"current_open\"`\n\tTotalOpened int `json:\"total_opened\"`\n}\n\ntype NodesStatsBreaker struct {\n\tLimitSize            string  `json:\"limit_size\"`\n\tLimitSizeInBytes     int64   `json:\"limit_size_in_bytes\"`\n\tEstimatedSize        string  `json:\"estimated_size\"`\n\tEstimatedSizeInBytes int64   `json:\"estimated_size_in_bytes\"`\n\tOverhead             float64 `json:\"overhead\"`\n\tTripped              int64   `json:\"tripped\"`\n}\n\ntype NodesStatsScriptStats struct {\n\tCompilations   int64 `json:\"compilations\"`\n\tCacheEvictions int64 `json:\"cache_evictions\"`\n}\n\ntype NodesStatsDiscovery struct {\n\tClusterStateQueue *NodesStatsDiscoveryStats `json:\"cluster_state_queue\"`\n}\n\ntype NodesStatsDiscoveryStats struct {\n\tTotal     int64 `json:\"total\"`\n\tPending   int64 `json:\"pending\"`\n\tCommitted int64 `json:\"committed\"`\n}\n\ntype NodesStatsIngest struct {\n\tTotal     *NodesStatsIngestStats `json:\"total\"`\n\tPipelines interface{}            `json:\"pipelines\"`\n}\n\ntype NodesStatsIngestStats struct {\n\tCount        int64  `json:\"count\"`\n\tTime         string `json:\"time\"`\n\tTimeInMillis int64  `json:\"time_in_millis\"`\n\tCurrent      int64  `json:\"current\"`\n\tFailed       int64  `json:\"failed\"`\n}\n"
  },
  {
    "path": "nodes_stats_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestNodesStats(t *testing.T) {\n\tclient, err := NewClient() // SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// TODO(oe) Remove this hack after a fix for https://github.com/elastic/elasticsearch/issues/78311 is released\n\tversion, err := client.ElasticsearchVersion(DefaultURL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif version == \"7.15.0\" || version == \"7.15.1\" {\n\t\tt.Skipf(\"skipping NodesStats test for %s because of https://github.com/elastic/elasticsearch/issues/78311\", version)\n\t\treturn\n\t}\n\n\tinfo, err := client.NodesStats().Human(true).Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif info == nil {\n\t\tt.Fatal(\"expected nodes stats\")\n\t}\n\n\tif info.ClusterName == \"\" {\n\t\tt.Errorf(\"expected cluster name; got: %q\", info.ClusterName)\n\t}\n\tif len(info.Nodes) == 0 {\n\t\tt.Errorf(\"expected some nodes; got: %d\", len(info.Nodes))\n\t}\n\tfor id, node := range info.Nodes {\n\t\tif id == \"\" {\n\t\t\tt.Errorf(\"expected node id; got: %q\", id)\n\t\t}\n\t\tif node == nil {\n\t\t\tt.Fatalf(\"expected node info; got: %v\", node)\n\t\t}\n\t\tif len(node.Name) == 0 {\n\t\t\tt.Errorf(\"expected node name; got: %q\", node.Name)\n\t\t}\n\t\tif node.Timestamp == 0 {\n\t\t\tt.Errorf(\"expected timestamp; got: %q\", node.Timestamp)\n\t\t}\n\t}\n}\n\nfunc TestNodesStatsBuildURL(t *testing.T) {\n\ttests := []struct {\n\t\tNodeIds      []string\n\t\tMetrics      []string\n\t\tIndexMetrics []string\n\t\tExpected     string\n\t}{\n\t\t{\n\t\t\tNodeIds:      nil,\n\t\t\tMetrics:      nil,\n\t\t\tIndexMetrics: nil,\n\t\t\tExpected:     \"/_nodes/stats\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      []string{\"node1\"},\n\t\t\tMetrics:      nil,\n\t\t\tIndexMetrics: nil,\n\t\t\tExpected:     \"/_nodes/node1/stats\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      []string{\"node1\", \"node2\"},\n\t\t\tMetrics:      nil,\n\t\t\tIndexMetrics: nil,\n\t\t\tExpected:     \"/_nodes/node1%2Cnode2/stats\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      nil,\n\t\t\tMetrics:      []string{\"indices\"},\n\t\t\tIndexMetrics: nil,\n\t\t\tExpected:     \"/_nodes/stats/indices\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      nil,\n\t\t\tMetrics:      []string{\"indices\", \"jvm\"},\n\t\t\tIndexMetrics: nil,\n\t\t\tExpected:     \"/_nodes/stats/indices%2Cjvm\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      []string{\"node1\"},\n\t\t\tMetrics:      []string{\"indices\", \"jvm\"},\n\t\t\tIndexMetrics: nil,\n\t\t\tExpected:     \"/_nodes/node1/stats/indices%2Cjvm\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      nil,\n\t\t\tMetrics:      nil,\n\t\t\tIndexMetrics: []string{\"fielddata\"},\n\t\t\tExpected:     \"/_nodes/stats/_all/fielddata\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      []string{\"node1\"},\n\t\t\tMetrics:      nil,\n\t\t\tIndexMetrics: []string{\"fielddata\"},\n\t\t\tExpected:     \"/_nodes/node1/stats/_all/fielddata\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      nil,\n\t\t\tMetrics:      []string{\"indices\"},\n\t\t\tIndexMetrics: []string{\"fielddata\"},\n\t\t\tExpected:     \"/_nodes/stats/indices/fielddata\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      []string{\"node1\"},\n\t\t\tMetrics:      []string{\"indices\"},\n\t\t\tIndexMetrics: []string{\"fielddata\"},\n\t\t\tExpected:     \"/_nodes/node1/stats/indices/fielddata\",\n\t\t},\n\t\t{\n\t\t\tNodeIds:      []string{\"node1\", \"node2\"},\n\t\t\tMetrics:      []string{\"indices\", \"jvm\"},\n\t\t\tIndexMetrics: []string{\"fielddata\", \"docs\"},\n\t\t\tExpected:     \"/_nodes/node1%2Cnode2/stats/indices%2Cjvm/fielddata%2Cdocs\",\n\t\t},\n\t}\n\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfor i, tt := range tests {\n\t\tsvc := client.NodesStats().NodeId(tt.NodeIds...).Metric(tt.Metrics...).IndexMetric(tt.IndexMetrics...)\n\t\tpath, _, err := svc.buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"#%d: expected no error, got %v\", i, err)\n\t\t} else {\n\t\t\tif want, have := tt.Expected, path; want != have {\n\t\t\t\tt.Errorf(\"#%d: expected %q, got %q\", i, want, have)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "percolate_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestPercolate(t *testing.T) {\n\t//client := setupTestClientAndCreateIndex(t, SetErrorLog(log.New(os.Stdout, \"\", 0)))\n\t//client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// Create query index\n\tcreateQueryIndex, err := client.CreateIndex(testQueryIndex).Body(testQueryMapping).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createQueryIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createQueryIndex)\n\t}\n\n\t// Add a document\n\t_, err = client.Index().\n\t\tIndex(testQueryIndex).\n\t\tId(\"1\").\n\t\tBodyJson(`{\"query\":{\"match\":{\"message\":\"bonsai tree\"}}}`).\n\t\tRefresh(\"wait_for\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Percolate should return our registered query\n\tpq := NewPercolatorQuery().\n\t\tField(\"query\").\n\t\tDocument(doctype{Message: \"A new bonsai tree in the office\"})\n\tres, err := client.Search(testQueryIndex).Query(pq).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected results != nil; got nil\")\n\t}\n\tif res.Hits == nil {\n\t\tt.Fatal(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := res.TotalHits(), int64(1); got != want {\n\t\tt.Fatalf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(res.Hits.Hits), 1; got != want {\n\t\tt.Fatalf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n\thit := res.Hits.Hits[0]\n\tif hit.Index != testQueryIndex {\n\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testQueryIndex, hit.Index)\n\t}\n\tgot := string(hit.Source)\n\texpected := `{\"query\":{\"match\":{\"message\":\"bonsai tree\"}}}`\n\tif got != expected {\n\t\tt.Fatalf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "ping.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"runtime\"\n\t\"strings\"\n)\n\n// PingService checks if an Elasticsearch server on a given URL is alive.\n// When asked for, it can also return various information about the\n// Elasticsearch server, e.g. the Elasticsearch version number.\n//\n// Ping simply starts a HTTP GET request to the URL of the server.\n// If the server responds with HTTP Status code 200 OK, the server is alive.\ntype PingService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\turl          string\n\ttimeout      string\n\thttpHeadOnly bool\n}\n\n// PingResult is the result returned from querying the Elasticsearch server.\ntype PingResult struct {\n\tName        string `json:\"name\"`\n\tClusterName string `json:\"cluster_name\"`\n\tVersion     struct {\n\t\tNumber                           string `json:\"number\"`                              // e.g. \"7.0.0\"\n\t\tBuildFlavor                      string `json:\"build_flavor\"`                        // e.g. \"oss\" or \"default\"\n\t\tBuildType                        string `json:\"build_type\"`                          // e.g. \"docker\"\n\t\tBuildHash                        string `json:\"build_hash\"`                          // e.g. \"b7e28a7\"\n\t\tBuildDate                        string `json:\"build_date\"`                          // e.g. \"2019-04-05T22:55:32.697037Z\"\n\t\tBuildSnapshot                    bool   `json:\"build_snapshot\"`                      // e.g. false\n\t\tLuceneVersion                    string `json:\"lucene_version\"`                      // e.g. \"8.0.0\"\n\t\tMinimumWireCompatibilityVersion  string `json:\"minimum_wire_compatibility_version\"`  // e.g. \"6.7.0\"\n\t\tMinimumIndexCompatibilityVersion string `json:\"minimum_index_compatibility_version\"` // e.g. \"6.0.0-beta1\"\n\t} `json:\"version\"`\n\tTagLine string `json:\"tagline\"`\n}\n\nfunc NewPingService(client *Client) *PingService {\n\treturn &PingService{\n\t\tclient:       client,\n\t\turl:          DefaultURL,\n\t\thttpHeadOnly: false,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *PingService) Pretty(pretty bool) *PingService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *PingService) Human(human bool) *PingService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *PingService) ErrorTrace(errorTrace bool) *PingService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *PingService) FilterPath(filterPath ...string) *PingService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *PingService) Header(name string, value string) *PingService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *PingService) Headers(headers http.Header) *PingService {\n\ts.headers = headers\n\treturn s\n}\n\nfunc (s *PingService) URL(url string) *PingService {\n\ts.url = url\n\treturn s\n}\n\nfunc (s *PingService) Timeout(timeout string) *PingService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// HeadOnly makes the service to only return the status code in Do;\n// the PingResult will be nil.\nfunc (s *PingService) HttpHeadOnly(httpHeadOnly bool) *PingService {\n\ts.httpHeadOnly = httpHeadOnly\n\treturn s\n}\n\n// Do returns the PingResult, the HTTP status code of the Elasticsearch\n// server, and an error.\nfunc (s *PingService) Do(ctx context.Context) (*PingResult, int, error) {\n\ts.client.mu.RLock()\n\tbasicAuth := s.client.basicAuthUsername != \"\" || s.client.basicAuthPassword != \"\"\n\tbasicAuthUsername := s.client.basicAuthUsername\n\tbasicAuthPassword := s.client.basicAuthPassword\n\tdefaultHeaders := s.client.headers\n\ts.client.mu.RUnlock()\n\n\turl_ := strings.TrimSuffix(s.url, \"/\") + \"/\"\n\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif len(params) > 0 {\n\t\turl_ += \"?\" + params.Encode()\n\t}\n\n\tvar method string\n\tif s.httpHeadOnly {\n\t\tmethod = \"HEAD\"\n\t} else {\n\t\tmethod = \"GET\"\n\t}\n\n\t// Notice: This service must NOT use PerformRequest!\n\treq, err := NewRequest(method, url_)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\tfor key, values := range s.headers {\n\t\tfor _, v := range values {\n\t\t\treq.Header.Add(key, v)\n\t\t}\n\t}\n\tif len(defaultHeaders) > 0 {\n\t\tfor key, values := range defaultHeaders {\n\t\t\tfor _, v := range values {\n\t\t\t\treq.Header.Add(key, v)\n\t\t\t}\n\t\t}\n\t}\n\n\tif basicAuth {\n\t\treq.SetBasicAuth(basicAuthUsername, basicAuthPassword)\n\t}\n\n\tif req.Header.Get(\"User-Agent\") == \"\" {\n\t\treq.Header.Add(\"User-Agent\", \"elastic/\"+Version+\" (\"+runtime.GOOS+\"-\"+runtime.GOARCH+\")\")\n\t}\n\n\tres, err := s.client.c.Do((*http.Request)(req).WithContext(ctx))\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\tdefer res.Body.Close()\n\n\tvar ret *PingResult\n\tif !s.httpHeadOnly {\n\t\tret = new(PingResult)\n\t\tif err := json.NewDecoder(res.Body).Decode(ret); err != nil {\n\t\t\treturn nil, res.StatusCode, err\n\t\t}\n\t}\n\n\treturn ret, res.StatusCode, nil\n}\n"
  },
  {
    "path": "ping_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"testing\"\n)\n\nfunc TestPingGet(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tres, code, err := client.Ping(DefaultURL).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif code != http.StatusOK {\n\t\tt.Errorf(\"expected status code = %d; got %d\", http.StatusOK, code)\n\t}\n\tif res == nil {\n\t\tt.Fatalf(\"expected to return result, got: %v\", res)\n\t}\n\tif res.Name == \"\" {\n\t\tt.Errorf(\"expected Name != %q; got %q\", \"\", res.Name)\n\t}\n\tif res.Version.Number == \"\" {\n\t\tt.Errorf(\"expected Version.Number != %q; got %q\", \"\", res.Version.Number)\n\t}\n}\n\nfunc TestPingHead(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tres, code, err := client.Ping(DefaultURL).HttpHeadOnly(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif code != http.StatusOK {\n\t\tt.Errorf(\"expected status code = %d; got %d\", http.StatusOK, code)\n\t}\n\tif res != nil {\n\t\tt.Errorf(\"expected not to return result, got: %v\", res)\n\t}\n}\n\nfunc TestPingHeadFailure(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tres, code, err := client.\n\t\tPing(\"http://127.0.0.1:9299\").\n\t\tHttpHeadOnly(true).\n\t\tDo(context.TODO())\n\tif err == nil {\n\t\tt.Error(\"expected error, got nil\")\n\t}\n\tif code == http.StatusOK {\n\t\tt.Errorf(\"expected status code != %d; got %d\", http.StatusOK, code)\n\t}\n\tif res != nil {\n\t\tt.Errorf(\"expected not to return result, got: %v\", res)\n\t}\n}\n"
  },
  {
    "path": "pit.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// PointInTime is a lightweight view into the state of the data that existed\n// when initiated. It can be created with OpenPointInTime API and be used\n// when searching, e.g. in Search API or with SearchSource.\ntype PointInTime struct {\n\t// Id that uniquely identifies the point in time, as created with the\n\t// OpenPointInTime API.\n\tId string `json:\"id,omitempty\"`\n\t// KeepAlive is the time for which this specific PointInTime will be\n\t// kept alive by Elasticsearch.\n\tKeepAlive string `json:\"keep_alive,omitempty\"`\n}\n\n// NewPointInTime creates a new PointInTime.\nfunc NewPointInTime(id string) *PointInTime {\n\treturn &PointInTime{\n\t\tId: id,\n\t}\n}\n\n// NewPointInTimeWithKeepAlive creates a new PointInTime with the given\n// time to keep alive.\nfunc NewPointInTimeWithKeepAlive(id, keepAlive string) *PointInTime {\n\treturn &PointInTime{\n\t\tId:        id,\n\t\tKeepAlive: keepAlive,\n\t}\n}\n\n// Source generates the JSON serializable fragment for the PointInTime.\nfunc (pit *PointInTime) Source() (interface{}, error) {\n\tif pit == nil {\n\t\treturn nil, nil\n\t}\n\tm := map[string]interface{}{\n\t\t\"id\": pit.Id,\n\t}\n\tif pit.KeepAlive != \"\" {\n\t\tm[\"keep_alive\"] = pit.KeepAlive\n\t}\n\treturn m, nil\n}\n"
  },
  {
    "path": "pit_close.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// ClosePointInTimeService removes a point in time.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.x/point-in-time-api.html\n// for details.\ntype ClosePointInTimeService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid         string\n\tbodyJson   interface{}\n\tbodyString string\n}\n\n// NewClosePointInTimeService creates a new ClosePointInTimeService.\nfunc NewClosePointInTimeService(client *Client) *ClosePointInTimeService {\n\treturn &ClosePointInTimeService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ClosePointInTimeService) Pretty(pretty bool) *ClosePointInTimeService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ClosePointInTimeService) Human(human bool) *ClosePointInTimeService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ClosePointInTimeService) ErrorTrace(errorTrace bool) *ClosePointInTimeService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ClosePointInTimeService) FilterPath(filterPath ...string) *ClosePointInTimeService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ClosePointInTimeService) Header(name string, value string) *ClosePointInTimeService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ClosePointInTimeService) Headers(headers http.Header) *ClosePointInTimeService {\n\ts.headers = headers\n\treturn s\n}\n\n// ID to close.\nfunc (s *ClosePointInTimeService) ID(id string) *ClosePointInTimeService {\n\ts.id = id\n\treturn s\n}\n\n// BodyJson is the document as a serializable JSON interface.\nfunc (s *ClosePointInTimeService) BodyJson(body interface{}) *ClosePointInTimeService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the document encoded as a string.\nfunc (s *ClosePointInTimeService) BodyString(body string) *ClosePointInTimeService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ClosePointInTimeService) buildURL() (string, string, url.Values, error) {\n\tvar (\n\t\tmethod = \"DELETE\"\n\t\tpath   = \"/_pit\"\n\t)\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn method, path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ClosePointInTimeService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *ClosePointInTimeService) Do(ctx context.Context) (*ClosePointInTimeResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tmethod, path, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.id != \"\" {\n\t\tbody = map[string]interface{}{\n\t\t\t\"id\": s.id,\n\t\t}\n\t} else if s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  method,\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(ClosePointInTimeResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// ClosePointInTimeResponse is the result of closing a point in time.\ntype ClosePointInTimeResponse struct {\n\tSucceeded bool `json:\"succeeded,omitempty\"`\n\tNumFreed  int  `json:\"num_freed,omitempty\"`\n}\n"
  },
  {
    "path": "pit_open.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// OpenPointInTimeService opens a point in time that can be used in subsequent\n// searches.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.x/point-in-time-api.html\n// for details.\ntype OpenPointInTimeService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\tpreference        string\n\trouting           string\n\tignoreUnavailable *bool\n\texpandWildcards   string\n\tkeepAlive         string\n\tbodyJson          interface{}\n\tbodyString        string\n}\n\n// NewOpenPointInTimeService creates a new OpenPointInTimeService.\nfunc NewOpenPointInTimeService(client *Client) *OpenPointInTimeService {\n\treturn &OpenPointInTimeService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *OpenPointInTimeService) Pretty(pretty bool) *OpenPointInTimeService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *OpenPointInTimeService) Human(human bool) *OpenPointInTimeService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *OpenPointInTimeService) ErrorTrace(errorTrace bool) *OpenPointInTimeService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *OpenPointInTimeService) FilterPath(filterPath ...string) *OpenPointInTimeService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *OpenPointInTimeService) Header(name string, value string) *OpenPointInTimeService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *OpenPointInTimeService) Headers(headers http.Header) *OpenPointInTimeService {\n\ts.headers = headers\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be performed on.\nfunc (s *OpenPointInTimeService) Preference(preference string) *OpenPointInTimeService {\n\ts.preference = preference\n\treturn s\n}\n\n// Index is the name of the index (or indices).\nfunc (s *OpenPointInTimeService) Index(index ...string) *OpenPointInTimeService {\n\ts.index = index\n\treturn s\n}\n\n// Routing is a specific routing value.\nfunc (s *OpenPointInTimeService) Routing(routing string) *OpenPointInTimeService {\n\ts.routing = routing\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *OpenPointInTimeService) IgnoreUnavailable(ignoreUnavailable bool) *OpenPointInTimeService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *OpenPointInTimeService) ExpandWildcards(expandWildcards string) *OpenPointInTimeService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// KeepAlive indicates the specific time to live for the point in time.\nfunc (s *OpenPointInTimeService) KeepAlive(keepAlive string) *OpenPointInTimeService {\n\ts.keepAlive = keepAlive\n\treturn s\n}\n\n// BodyJson is the document as a serializable JSON interface.\nfunc (s *OpenPointInTimeService) BodyJson(body interface{}) *OpenPointInTimeService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the document encoded as a string.\nfunc (s *OpenPointInTimeService) BodyString(body string) *OpenPointInTimeService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *OpenPointInTimeService) buildURL() (string, string, url.Values, error) {\n\tvar err error\n\tvar method, path string\n\n\tif len(s.index) > 0 {\n\t\tmethod = \"POST\"\n\t\tpath, err = uritemplates.Expand(\"/{index}/_pit\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tmethod = \"POST\"\n\t\tpath = \"/_pit\"\n\t}\n\tif err != nil {\n\t\treturn \"\", \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.keepAlive != \"\" {\n\t\tparams.Set(\"keep_alive\", s.keepAlive)\n\t}\n\treturn method, path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *OpenPointInTimeService) Validate() error {\n\tvar invalid []string\n\tif len(s.index) == 0 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif s.keepAlive == \"\" {\n\t\tinvalid = append(invalid, \"KeepAlive\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *OpenPointInTimeService) Do(ctx context.Context) (*OpenPointInTimeResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tmethod, path, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  method,\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(OpenPointInTimeResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// OpenPointInTimeResponse is the result of opening a point in time.\ntype OpenPointInTimeResponse struct {\n\tId string `json:\"id,omitempty\"`\n}\n"
  },
  {
    "path": "pit_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestPointInTimeOpenAndClose(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Create a Point In Time\n\topenResp, err := client.OpenPointInTime(testIndexName).\n\t\tKeepAlive(\"1m\").\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif openResp == nil {\n\t\tt.Fatal(\"expected non-nil Point In Time\")\n\t}\n\tif openResp.Id == \"\" {\n\t\tt.Fatal(\"expected non-blank Point In Time ID\")\n\t}\n\n\t// Close the Point in Time\n\tcloseResp, err := client.ClosePointInTime(openResp.Id).Pretty(true).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif closeResp == nil {\n\t\tt.Fatal(\"expected non-nil Point In Time\")\n\t}\n\tif want, have := true, closeResp.Succeeded; want != have {\n\t\tt.Fatalf(\"want Succeeded=%v, have %v\", want, have)\n\t}\n\tif want, have := 1, closeResp.NumFreed; want != have {\n\t\tt.Fatalf(\"want NumFreed=%v, have %v\", want, have)\n\t}\n}\n\nfunc TestPointInTimeLifecycle(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Create a Point In Time\n\tpitResp, err := client.OpenPointInTime().\n\t\tIndex(testIndexName).\n\t\tKeepAlive(\"1m\").\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif pitResp == nil {\n\t\tt.Fatal(\"expected non-nil Point In Time\")\n\t}\n\tif pitResp.Id == \"\" {\n\t\tt.Fatal(\"expected non-blank Point In Time ID\")\n\t}\n\n\t// We remove the documents here, but will be able to still search with\n\t// the PIT previously created\n\t_, err = client.DeleteByQuery(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tRefresh(\"true\").\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Search with the Point in Time ID\n\tsearchResult, err := client.Search().\n\t\t// Index(testIndexName). // <-- you may not use indices with PointInTime!\n\t\tQuery(NewMatchAllQuery()).\n\t\tPointInTime(NewPointInTimeWithKeepAlive(pitResp.Id, \"1m\")).\n\t\tSize(100).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(3); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\n}\n"
  },
  {
    "path": "plugins.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"context\"\n\n// HasPlugin indicates whether the cluster has the named plugin.\nfunc (c *Client) HasPlugin(name string) (bool, error) {\n\tplugins, err := c.Plugins()\n\tif err != nil {\n\t\treturn false, nil\n\t}\n\tfor _, plugin := range plugins {\n\t\tif plugin == name {\n\t\t\treturn true, nil\n\t\t}\n\t}\n\treturn false, nil\n}\n\n// Plugins returns the list of all registered plugins.\nfunc (c *Client) Plugins() ([]string, error) {\n\tstats, err := c.ClusterStats().Do(context.Background())\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif stats == nil {\n\t\treturn nil, err\n\t}\n\tif stats.Nodes == nil {\n\t\treturn nil, err\n\t}\n\tvar plugins []string\n\tfor _, plugin := range stats.Nodes.Plugins {\n\t\tplugins = append(plugins, plugin.Name)\n\t}\n\treturn plugins, nil\n}\n"
  },
  {
    "path": "plugins_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestClientPlugins(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_, err = client.Plugins()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n\nfunc TestClientHasPlugin(t *testing.T) {\n\tclient, err := NewClient()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tfound, err := client.HasPlugin(\"no-such-plugin\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif found {\n\t\tt.Fatalf(\"expected to not find plugin %q\", \"no-such-plugin\")\n\t}\n}\n"
  },
  {
    "path": "query.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// Query represents the generic query interface. A query's sole purpose\n// is to return the source of the query as a JSON-serializable object.\n// Returning map[string]interface{} is the norm for queries.\ntype Query interface {\n\t// Source returns the JSON-serializable query request.\n\tSource() (interface{}, error)\n}\n"
  },
  {
    "path": "recipes/aws-connect/.gitignore",
    "content": "/aws-connect\n"
  },
  {
    "path": "recipes/aws-connect/main.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Connect simply connects to Elasticsearch Service on AWS.\n//\n// Example\n//\n//     aws-connect -url=https://search-xxxxx-yyyyy.eu-central-1.es.amazonaws.com\n//\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/olivere/env\"\n\tawsauth \"github.com/smartystreets/go-aws-auth\"\n\n\t\"github.com/olivere/elastic/v7\"\n\t\"github.com/olivere/elastic/v7/aws\"\n)\n\nfunc main() {\n\tvar (\n\t\taccessKey = flag.String(\"access-key\", env.String(\"\", \"AWS_ACCESS_KEY\"), \"Access Key ID\")\n\t\tsecretKey = flag.String(\"secret-key\", env.String(\"\", \"AWS_SECRET_KEY\"), \"Secret access key\")\n\t\turl       = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tsniff     = flag.Bool(\"sniff\", false, \"Enable or disable sniffing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\t*url = \"http://127.0.0.1:9200\"\n\t}\n\tif *accessKey == \"\" {\n\t\tlog.Fatal(\"missing -access-key or AWS_ACCESS_KEY environment variable\")\n\t}\n\tif *secretKey == \"\" {\n\t\tlog.Fatal(\"missing -secret-key or AWS_SECRET_KEY environment variable\")\n\t}\n\n\tsigningClient := aws.NewV4SigningClient(awsauth.Credentials{\n\t\tAccessKeyID:     *accessKey,\n\t\tSecretAccessKey: *secretKey,\n\t})\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(*url),\n\t\telastic.SetSniff(*sniff),\n\t\telastic.SetHealthcheck(*sniff),\n\t\telastic.SetHttpClient(signingClient),\n\t)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t_ = client\n\n\t// Just a status message\n\tfmt.Println(\"Connection succeeded\")\n}\n"
  },
  {
    "path": "recipes/aws-connect-v4/.gitignore",
    "content": "/aws-connect-v4\n"
  },
  {
    "path": "recipes/aws-connect-v4/main.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Connect simply connects to Elasticsearch Service on AWS.\n//\n// Example\n//\n//     aws-connect-v4 -url=https://search-xxxxx-yyyyy.eu-central-1.es.amazonaws.com\n//\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/aws/aws-sdk-go/aws/credentials\"\n\t\"github.com/olivere/env\"\n\n\t\"github.com/olivere/elastic/v7\"\n\taws \"github.com/olivere/elastic/v7/aws/v4\"\n)\n\nfunc main() {\n\tvar (\n\t\taccessKey = flag.String(\"access-key\", env.String(\"\", \"AWS_ACCESS_KEY\", \"AWS_ACCESS_KEY_ID\"), \"Access Key ID\")\n\t\tsecretKey = flag.String(\"secret-key\", env.String(\"\", \"AWS_SECRET_KEY\", \"AWS_SECRET_ACCESS_KEY\"), \"Secret access key\")\n\t\turl       = flag.String(\"url\", \"\", \"Elasticsearch URL\")\n\t\tsniff     = flag.Bool(\"sniff\", false, \"Enable or disable sniffing\")\n\t\tregion    = flag.String(\"region\", \"eu-west-1\", \"AWS Region name\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\tlog.Fatal(\"please specify a URL with -url\")\n\t}\n\tif *accessKey == \"\" {\n\t\tlog.Fatal(\"missing -access-key or AWS_ACCESS_KEY environment variable\")\n\t}\n\tif *secretKey == \"\" {\n\t\tlog.Fatal(\"missing -secret-key or AWS_SECRET_KEY environment variable\")\n\t}\n\tif *region == \"\" {\n\t\tlog.Fatal(\"please specify an AWS region with -region\")\n\t}\n\n\tsigningClient := aws.NewV4SigningClient(credentials.NewStaticCredentials(\n\t\t*accessKey,\n\t\t*secretKey,\n\t\t\"\",\n\t), *region)\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(*url),\n\t\telastic.SetSniff(*sniff),\n\t\telastic.SetHealthcheck(*sniff),\n\t\telastic.SetHttpClient(signingClient),\n\t)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t_ = client\n\n\t// Just a status message\n\tfmt.Println(\"Connection succeeded\")\n}\n"
  },
  {
    "path": "recipes/aws-mapping-v4/.gitignore",
    "content": "/aws-mapping-v4\n"
  },
  {
    "path": "recipes/aws-mapping-v4/main.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Connect creates an index with a mapping with different data types.\n//\n// Example\n//\n//\n//     aws-mapping-v4 -url=https://search-xxxxx-yyyyy.eu-central-1.es.amazonaws.com -index=twitter -type=tweet -sniff=false\n//\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/aws/aws-sdk-go/aws/credentials\"\n\t\"github.com/olivere/env\"\n\n\t\"github.com/olivere/elastic/v7\"\n\taws \"github.com/olivere/elastic/v7/aws/v4\"\n)\n\nconst (\n\tmapping = `\n\t{\n\t\t\"settings\":{\n\t\t\t\"number_of_shards\":1,\n\t\t\t\"number_of_replicas\":0\n\t\t},\n\t\t\"mappings\":{\n\t\t\t\"_doc\":{\n\t\t\t\t\"properties\":{\n\t\t\t\t\t\"user\":{\n\t\t\t\t\t\t\"type\":\"keyword\"\n\t\t\t\t\t},\n\t\t\t\t\t\"message\":{\n\t\t\t\t\t\t\"type\":\"text\"\n\t\t\t\t\t},\n\t\t\t\t\t\"retweets\":{\n\t\t\t\t\t\t\"type\":\"integer\"\n\t\t\t\t\t},\n\t\t\t\t\t\"created\":{\n\t\t\t\t\t\t\"type\":\"date\"\n\t\t\t\t\t},\n\t\t\t\t\t\"attributes\":{\n\t\t\t\t\t\t\"type\":\"object\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t`\n)\n\n// Tweet is just an example document.\ntype Tweet struct {\n\tUser     string                 `json:\"user\"`\n\tMessage  string                 `json:\"message\"`\n\tRetweets int                    `json:\"retweets\"`\n\tCreated  time.Time              `json:\"created\"`\n\tAttrs    map[string]interface{} `json:\"attributes,omitempty\"`\n}\n\nfunc main() {\n\tvar (\n\t\taccessKey = flag.String(\"access-key\", env.String(\"\", \"AWS_ACCESS_KEY\", \"AWS_ACCESS_KEY_ID\"), \"Access Key ID\")\n\t\tsecretKey = flag.String(\"secret-key\", env.String(\"\", \"AWS_SECRET_KEY\", \"AWS_SECRET_ACCESS_KEY\"), \"Secret access key\")\n\t\turl       = flag.String(\"url\", \"\", \"Elasticsearch URL\")\n\t\tsniff     = flag.Bool(\"sniff\", false, \"Enable or disable sniffing\")\n\t\ttrace     = flag.Bool(\"trace\", false, \"Enable or disable tracing\")\n\t\tindex     = flag.String(\"index\", \"\", \"Index name\")\n\t\tregion    = flag.String(\"region\", \"eu-west-1\", \"AWS Region name\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(log.LstdFlags | log.Lshortfile)\n\n\tif *url == \"\" {\n\t\tlog.Fatal(\"please specify a URL with -url\")\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"please specify an index name with -index\")\n\t}\n\tif *region == \"\" {\n\t\tlog.Fatal(\"please specify an AWS region with -region\")\n\t}\n\n\t// Create an Elasticsearch client\n\tsigningClient := aws.NewV4SigningClient(credentials.NewStaticCredentials(\n\t\t*accessKey,\n\t\t*secretKey,\n\t\t\"\",\n\t), *region)\n\n\t// Create an Elasticsearch client\n\topts := []elastic.ClientOptionFunc{\n\t\telastic.SetURL(*url),\n\t\telastic.SetSniff(*sniff),\n\t\telastic.SetHealthcheck(*sniff),\n\t\telastic.SetHttpClient(signingClient),\n\t}\n\tif *trace {\n\t\topts = append(opts, elastic.SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\t}\n\tclient, err := elastic.NewClient(opts...)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Check if index already exists. We'll drop it then.\n\t// Next, we create a fresh index/mapping.\n\tctx := context.Background()\n\texists, err := client.IndexExists(*index).Pretty(true).Do(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif exists {\n\t\t_, err := client.DeleteIndex(*index).Pretty(true).Do(ctx)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\t_, err = client.CreateIndex(*index).Body(mapping).Pretty(true).Do(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Add a tweet\n\t{\n\t\ttweet := Tweet{\n\t\t\tUser:     \"olivere\",\n\t\t\tMessage:  \"Welcome to Go and Elasticsearch.\",\n\t\t\tRetweets: 0,\n\t\t\tCreated:  time.Now(),\n\t\t\tAttrs: map[string]interface{}{\n\t\t\t\t\"views\": 17,\n\t\t\t\t\"vip\":   true,\n\t\t\t},\n\t\t}\n\t\t_, err := client.Index().\n\t\t\tIndex(*index).\n\t\t\tType(\"_doc\").\n\t\t\tId(\"1\").\n\t\t\tBodyJson(&tweet).\n\t\t\tRefresh(\"true\").\n\t\t\tPretty(true).\n\t\t\tDo(context.TODO())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\n\t// Read the tweet\n\t{\n\t\tdoc, err := client.Get().\n\t\t\tIndex(*index).\n\t\t\tType(\"_doc\").\n\t\t\tId(\"1\").\n\t\t\tPretty(true).\n\t\t\tDo(context.TODO())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tvar tweet Tweet\n\t\tif err = json.Unmarshal(doc.Source, &tweet); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"%s at %s: %s (%d retweets)\\n\",\n\t\t\ttweet.User,\n\t\t\ttweet.Created,\n\t\t\ttweet.Message,\n\t\t\ttweet.Retweets,\n\t\t)\n\t\tfmt.Printf(\"  %v\\n\", tweet.Attrs)\n\t}\n}\n"
  },
  {
    "path": "recipes/bulk_insert/.gitignore",
    "content": "/bulk_insert\n"
  },
  {
    "path": "recipes/bulk_insert/bulk_insert.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// BulkInsert illustrates how to bulk insert documents into Elasticsearch.\n//\n// It uses two goroutines to do so. The first creates a simple document\n// and sends it to the second via a channel. The second goroutine collects\n// those documents, creates a bulk request that is added to a Bulk service\n// and committed to Elasticsearch after reaching a number of documents.\n// The number of documents after which a commit happens can be specified\n// via the \"bulk-size\" flag.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-bulk.html\n// for details on the Bulk API in Elasticsearch.\n//\n// Example\n//\n// Bulk index 100.000 documents into the index \"warehouse\", type \"product\",\n// committing every set of 1.000 documents.\n//\n//     bulk_insert -index=warehouse -type=product -n=100000 -bulk-size=1000\n//\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc main() {\n\tvar (\n\t\turl      = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tindex    = flag.String(\"index\", \"\", \"Elasticsearch index name\")\n\t\ttyp      = flag.String(\"type\", \"\", \"Elasticsearch type name\")\n\t\tsniff    = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t\tn        = flag.Int(\"n\", 0, \"Number of documents to bulk insert\")\n\t\tbulkSize = flag.Int(\"bulk-size\", 0, \"Number of documents to collect before committing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\trand.Seed(time.Now().UnixNano())\n\n\tif *url == \"\" {\n\t\tlog.Fatal(\"missing url parameter\")\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"missing index parameter\")\n\t}\n\tif *typ == \"\" {\n\t\tlog.Fatal(\"missing type parameter\")\n\t}\n\tif *n <= 0 {\n\t\tlog.Fatal(\"n must be a positive number\")\n\t}\n\tif *bulkSize <= 0 {\n\t\tlog.Fatal(\"bulk-size must be a positive number\")\n\t}\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(elastic.SetURL(*url), elastic.SetSniff(*sniff))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Setup a group of goroutines from the excellent errgroup package\n\tg, ctx := errgroup.WithContext(context.TODO())\n\n\t// The first goroutine will emit documents and send it to the second goroutine\n\t// via the docsc channel.\n\t// The second Goroutine will simply bulk insert the documents.\n\ttype doc struct {\n\t\tID        string    `json:\"id\"`\n\t\tTimestamp time.Time `json:\"@timestamp\"`\n\t}\n\tdocsc := make(chan doc)\n\n\tbegin := time.Now()\n\n\t// Goroutine to create documents\n\tg.Go(func() error {\n\t\tdefer close(docsc)\n\n\t\tbuf := make([]byte, 32)\n\t\tfor i := 0; i < *n; i++ {\n\t\t\t// Generate a random ID\n\t\t\t_, err := rand.Read(buf)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tid := base64.URLEncoding.EncodeToString(buf)\n\n\t\t\t// Construct the document\n\t\t\td := doc{\n\t\t\t\tID:        id,\n\t\t\t\tTimestamp: time.Now(),\n\t\t\t}\n\n\t\t\t// Send over to 2nd goroutine, or cancel\n\t\t\tselect {\n\t\t\tcase docsc <- d:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Second goroutine will consume the documents sent from the first and bulk insert into ES\n\tvar total uint64\n\tg.Go(func() error {\n\t\tbulk := client.Bulk().Index(*index).Type(*typ)\n\t\tfor d := range docsc {\n\t\t\t// Simple progress\n\t\t\tcurrent := atomic.AddUint64(&total, 1)\n\t\t\tdur := time.Since(begin).Seconds()\n\t\t\tsec := int(dur)\n\t\t\tpps := int64(float64(current) / dur)\n\t\t\tfmt.Printf(\"%10d | %6d req/s | %02d:%02d\\r\", current, pps, sec/60, sec%60)\n\n\t\t\t// Enqueue the document\n\t\t\tbulk.Add(elastic.NewBulkIndexRequest().Id(d.ID).Doc(d))\n\t\t\tif bulk.NumberOfActions() >= *bulkSize {\n\t\t\t\t// Commit\n\t\t\t\tres, err := bulk.Do(ctx)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif res.Errors {\n\t\t\t\t\t// Look up the failed documents with res.Failed(), and e.g. recommit\n\t\t\t\t\treturn errors.New(\"bulk commit failed\")\n\t\t\t\t}\n\t\t\t\t// \"bulk\" is reset after Do, so you can reuse it\n\t\t\t}\n\n\t\t\tselect {\n\t\t\tdefault:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\t\t}\n\n\t\t// Commit the final batch before exiting\n\t\tif bulk.NumberOfActions() > 0 {\n\t\t\t_, err = bulk.Do(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Wait until all goroutines are finished\n\tif err := g.Wait(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Final results\n\tdur := time.Since(begin).Seconds()\n\tsec := int(dur)\n\tpps := int64(float64(total) / dur)\n\tfmt.Printf(\"%10d | %6d req/s | %02d:%02d\\n\", total, pps, sec/60, sec%60)\n}\n"
  },
  {
    "path": "recipes/bulk_processor/.gitignore",
    "content": "/bulk_processor\n"
  },
  {
    "path": "recipes/bulk_processor/main.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// BulkProcessor runs a bulk processing job that fills an index\n// given certain criteria like flush interval etc.\n//\n// Example\n//\n//     bulk_processor -url=http://127.0.0.1:9200/bulk-processor-test?sniff=false -n=100000 -flush-interval=1s\n//\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"os\"\n\t\"os/signal\"\n\t\"sync/atomic\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\n\t\"github.com/olivere/elastic/v7\"\n\t\"github.com/olivere/elastic/v7/config\"\n)\n\nfunc main() {\n\tvar (\n\t\turl           = flag.String(\"url\", \"http://localhost:9200/bulk-processor-test\", \"Elasticsearch URL\")\n\t\tnumWorkers    = flag.Int(\"num-workers\", 4, \"Number of workers\")\n\t\tn             = flag.Int64(\"n\", -1, \"Number of documents to process (-1 for unlimited)\")\n\t\tflushInterval = flag.Duration(\"flush-interval\", 1*time.Second, \"Flush interval\")\n\t\tbulkActions   = flag.Int(\"bulk-actions\", 0, \"Number of bulk actions before committing\")\n\t\tbulkSize      = flag.Int(\"bulk-size\", 0, \"Size of bulk requests before committing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\trand.Seed(time.Now().UnixNano())\n\n\t// Parse configuration from URL\n\tcfg, err := config.Parse(*url)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Create an Elasticsearch client from the parsed config\n\tclient, err := elastic.NewClientFromConfig(cfg)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Drop old index\n\texists, err := client.IndexExists(cfg.Index).Do(context.Background())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif exists {\n\t\t_, err = client.DeleteIndex(cfg.Index).Do(context.Background())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\n\t// Create processor\n\tbulkp := elastic.NewBulkProcessorService(client).\n\t\tName(\"bulk-test-processor\").\n\t\tStats(true).\n\t\tBackoff(elastic.StopBackoff{}).\n\t\tFlushInterval(*flushInterval).\n\t\tWorkers(*numWorkers)\n\tif *bulkActions > 0 {\n\t\tbulkp = bulkp.BulkActions(*bulkActions)\n\t}\n\tif *bulkSize > 0 {\n\t\tbulkp = bulkp.BulkSize(*bulkSize)\n\t}\n\tp, err := bulkp.Do(context.Background())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tvar created int64\n\terrc := make(chan error, 1)\n\tgo func() {\n\t\tc := make(chan os.Signal, 1)\n\t\tsignal.Notify(c, syscall.SIGINT, syscall.SIGTERM)\n\t\t<-c\n\t\terrc <- nil\n\t}()\n\n\tgo func() {\n\t\tdefer func() {\n\t\t\tif err := p.Close(); err != nil {\n\t\t\t\terrc <- err\n\t\t\t}\n\t\t}()\n\n\t\ttype Doc struct {\n\t\t\tTimestamp time.Time `json:\"@timestamp\"`\n\t\t}\n\n\t\tfor {\n\t\t\tcurrent := atomic.AddInt64(&created, 1)\n\t\t\tif *n > 0 && current >= *n {\n\t\t\t\terrc <- nil\n\t\t\t\treturn\n\t\t\t}\n\t\t\tr := elastic.NewBulkIndexRequest().\n\t\t\t\tIndex(cfg.Index).\n\t\t\t\tId(uuid.New().String()).\n\t\t\t\tDoc(Doc{Timestamp: time.Now()})\n\t\t\tp.Add(r)\n\n\t\t\ttime.Sleep(time.Duration(rand.Intn(1000)) * time.Microsecond)\n\t\t}\n\t}()\n\n\tgo func() {\n\t\tt := time.NewTicker(1 * time.Second)\n\t\tdefer t.Stop()\n\t\tfor range t.C {\n\t\t\tstats := p.Stats()\n\t\t\twritten := atomic.LoadInt64(&created)\n\t\t\tvar queued int64\n\t\t\tfor _, w := range stats.Workers {\n\t\t\t\tqueued += w.Queued\n\t\t\t}\n\t\t\tfmt.Printf(\"Queued=%5d Written=%8d Succeeded=%8d Failed=%8d Committed=%6d Flushed=%6d\\n\",\n\t\t\t\tqueued,\n\t\t\t\twritten,\n\t\t\t\tstats.Succeeded,\n\t\t\t\tstats.Failed,\n\t\t\t\tstats.Committed,\n\t\t\t\tstats.Flushed,\n\t\t\t)\n\t\t}\n\t}()\n\n\tif err := <-errc; err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "recipes/connect/.gitignore",
    "content": "/connect\n"
  },
  {
    "path": "recipes/connect/connect.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Connect simply connects to Elasticsearch.\n//\n// Example\n//\n//\n//     connect -url=http://127.0.0.1:9200 -sniff=false\n//\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc main() {\n\tvar (\n\t\turl   = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tsniff = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\t*url = \"http://127.0.0.1:9200\"\n\t}\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(elastic.SetURL(*url), elastic.SetSniff(*sniff))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t_ = client\n\n\t// Just a status message\n\tfmt.Println(\"Connection succeeded\")\n}\n"
  },
  {
    "path": "recipes/connect_with_config/.gitignore",
    "content": "/connect_with_config\n"
  },
  {
    "path": "recipes/connect_with_config/connect_with_config.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Connect simply connects to Elasticsearch.\n//\n// Example\n//\n//\n//     connect \"http://127.0.0.1:9200/test-index?sniff=false&healthcheck=false\"\n//\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"runtime\"\n\n\t\"github.com/olivere/elastic/v7\"\n\t\"github.com/olivere/elastic/v7/config\"\n)\n\nfunc main() {\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\turl := flag.Arg(0)\n\tif url == \"\" {\n\t\turl = \"http://127.0.0.1:9200\"\n\t}\n\n\t// Parse the URL with the config package\n\tcfg, err := config.Parse(url)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClientFromConfig(cfg)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Get ES version\n\tesversion, err := client.ElasticsearchVersion(cfg.URL)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Just a status message\n\tfmt.Printf(\"Connection succeeded with %v, Elastic %v and Elasticsearch %s\\n\",\n\t\truntime.Version(),\n\t\telastic.Version,\n\t\tesversion,\n\t)\n}\n"
  },
  {
    "path": "recipes/go.mod",
    "content": "module github.com/olivere/elastic/v7/recipes\n\ngo 1.17\n\nrequire (\n\tgithub.com/aws/aws-sdk-go v1.43.21\n\tgithub.com/google/uuid v1.3.0\n\tgithub.com/olivere/elastic/v7 v7.0.0-00010101000000-000000000000\n\tgithub.com/olivere/env v1.1.0\n\tgithub.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9\n\tgithub.com/uber/jaeger-client-go v2.25.0+incompatible\n\tgithub.com/uber/jaeger-lib v2.2.0+incompatible\n\tgo.opentelemetry.io/otel v1.5.0\n\tgo.opentelemetry.io/otel/exporters/jaeger v1.5.0\n\tgo.opentelemetry.io/otel/sdk v1.5.0\n\tgolang.org/x/sync v0.0.0-20210220032951-036812b2e83c\n)\n\nrequire (\n\tgithub.com/VividCortex/gohistogram v1.0.0 // indirect\n\tgithub.com/go-kit/kit v0.10.0 // indirect\n\tgithub.com/go-logr/logr v1.2.2 // indirect\n\tgithub.com/go-logr/stdr v1.2.2 // indirect\n\tgithub.com/jmespath/go-jmespath v0.4.0 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/mailru/easyjson v0.7.7 // indirect\n\tgithub.com/opentracing/opentracing-go v1.2.0 // indirect\n\tgithub.com/pkg/errors v0.9.1 // indirect\n\tgithub.com/smartystreets/gunit v1.4.3 // indirect\n\tgo.opentelemetry.io/otel/trace v1.5.0 // indirect\n\tgo.uber.org/atomic v1.6.0 // indirect\n\tgolang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect\n)\n\nreplace github.com/olivere/elastic/v7 => ../../elastic\n"
  },
  {
    "path": "recipes/go.sum",
    "content": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=\ngithub.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=\ngithub.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=\ngithub.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=\ngithub.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=\ngithub.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=\ngithub.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=\ngithub.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=\ngithub.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=\ngithub.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=\ngithub.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=\ngithub.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=\ngithub.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=\ngithub.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=\ngithub.com/aws/aws-sdk-go v1.43.21 h1:E4S2eX3d2gKJyI/ISrcIrSwXwqjIvCK85gtBMt4sAPE=\ngithub.com/aws/aws-sdk-go v1.43.21/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=\ngithub.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=\ngithub.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=\ngithub.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=\ngithub.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=\ngithub.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=\ngithub.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=\ngithub.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=\ngithub.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=\ngithub.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=\ngithub.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=\ngithub.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=\ngithub.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=\ngithub.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=\ngithub.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=\ngithub.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=\ngithub.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=\ngithub.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=\ngithub.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=\ngithub.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=\ngithub.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=\ngithub.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=\ngithub.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=\ngithub.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=\ngithub.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=\ngithub.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=\ngithub.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=\ngithub.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=\ngithub.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=\ngithub.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=\ngithub.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=\ngithub.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=\ngithub.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=\ngithub.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=\ngithub.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=\ngithub.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=\ngithub.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=\ngithub.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs=\ngithub.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=\ngithub.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=\ngithub.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=\ngithub.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=\ngithub.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=\ngithub.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=\ngithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=\ngithub.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=\ngithub.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=\ngithub.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=\ngithub.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=\ngithub.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=\ngithub.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=\ngithub.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=\ngithub.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=\ngithub.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=\ngithub.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=\ngithub.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=\ngithub.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=\ngithub.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=\ngithub.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=\ngithub.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=\ngithub.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=\ngithub.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=\ngithub.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=\ngithub.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=\ngithub.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=\ngithub.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=\ngithub.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=\ngithub.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=\ngithub.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=\ngithub.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=\ngithub.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=\ngithub.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=\ngithub.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=\ngithub.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=\ngithub.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=\ngithub.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=\ngithub.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=\ngithub.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=\ngithub.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=\ngithub.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=\ngithub.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=\ngithub.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=\ngithub.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=\ngithub.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=\ngithub.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=\ngithub.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=\ngithub.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=\ngithub.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=\ngithub.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=\ngithub.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=\ngithub.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=\ngithub.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=\ngithub.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=\ngithub.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=\ngithub.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=\ngithub.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=\ngithub.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=\ngithub.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=\ngithub.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=\ngithub.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=\ngithub.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=\ngithub.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=\ngithub.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=\ngithub.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=\ngithub.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=\ngithub.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=\ngithub.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=\ngithub.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=\ngithub.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=\ngithub.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=\ngithub.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=\ngithub.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=\ngithub.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=\ngithub.com/olivere/env v1.1.0 h1:owp/uwMwhru5668JjMDp8UTG3JGT27GTCk4ufYQfaTw=\ngithub.com/olivere/env v1.1.0/go.mod h1:zaoXy53SjZfxqZBGiGrZCkuVLYPdwrc+vArPuUVhJdQ=\ngithub.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=\ngithub.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=\ngithub.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=\ngithub.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=\ngithub.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=\ngithub.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=\ngithub.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=\ngithub.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=\ngithub.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=\ngithub.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=\ngithub.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=\ngithub.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=\ngithub.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=\ngithub.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=\ngithub.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=\ngithub.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=\ngithub.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=\ngithub.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=\ngithub.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=\ngithub.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=\ngithub.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=\ngithub.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=\ngithub.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=\ngithub.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=\ngithub.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=\ngithub.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=\ngithub.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=\ngithub.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=\ngithub.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=\ngithub.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=\ngithub.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=\ngithub.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=\ngithub.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=\ngithub.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=\ngithub.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=\ngithub.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=\ngithub.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=\ngithub.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck=\ngithub.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=\ngithub.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 h1:hp2CYQUINdZMHdvTdXtPOY2ainKl4IoMcpAXEf2xj3Q=\ngithub.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=\ngithub.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=\ngithub.com/smartystreets/gunit v1.4.2/go.mod h1:ZjM1ozSIMJlAz/ay4SG8PeKF00ckUp+zMHZXV9/bvak=\ngithub.com/smartystreets/gunit v1.4.3 h1:yhnYXSXKK/R5vaUVGZD1zw4CQZqwtor7pp0VXBbMDrc=\ngithub.com/smartystreets/gunit v1.4.3/go.mod h1:ciyZ4dVTN2S8npQ4g9lMdARLX5XboUpcq5O7N6GlQmw=\ngithub.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=\ngithub.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=\ngithub.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=\ngithub.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=\ngithub.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=\ngithub.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=\ngithub.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=\ngithub.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U=\ngithub.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=\ngithub.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw=\ngithub.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=\ngithub.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=\ngithub.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=\ngithub.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=\ngo.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=\ngo.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=\ngo.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=\ngo.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=\ngo.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=\ngo.opentelemetry.io/otel v1.5.0 h1:DhCU8oR2sJH9rfnwPdoV/+BJ7UIN5kXHL8DuSGrPU8E=\ngo.opentelemetry.io/otel v1.5.0/go.mod h1:Jm/m+rNp/z0eqJc74H7LPwQ3G87qkU/AnnAydAjSAHk=\ngo.opentelemetry.io/otel/exporters/jaeger v1.5.0 h1:ZR7nhLSfLufS5AHk/iN11Q+W9XYwsJrVZ1Frb833d+Y=\ngo.opentelemetry.io/otel/exporters/jaeger v1.5.0/go.mod h1:rSeUArMBRe1eQLo1T0WxOazohN1M2mYThWJQmn1BjRQ=\ngo.opentelemetry.io/otel/sdk v1.5.0 h1:QKhWBbcOC9fDCZKCfPFjWTWpfIlJR+i9xiUDYrLVmZs=\ngo.opentelemetry.io/otel/sdk v1.5.0/go.mod h1:CU4J1v+7iEljnm1G14QjdFWOXUyYLHVh0Lh+/BTYyFg=\ngo.opentelemetry.io/otel/trace v1.5.0 h1:AKQZ9zJsBRFAp7zLdyGNkqG2rToCDIt3i5tcLzQlbmU=\ngo.opentelemetry.io/otel/trace v1.5.0/go.mod h1:sq55kfhjXYr1zVSyexg0w1mpa03AYXR5eyTkB9NPPdE=\ngo.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=\ngo.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=\ngo.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=\ngo.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=\ngo.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=\ngo.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=\ngo.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=\ngo.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=\ngo.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=\ngolang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=\ngolang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=\ngolang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=\ngolang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=\ngolang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=\ngolang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=\ngolang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=\ngolang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=\ngolang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20200103221440-774c71fcf114 h1:DnSr2mCsxyCE6ZgIkmcWUQY2R5cH/6wL7eIxEmQOMSE=\ngolang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngoogle.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=\ngoogle.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=\ngoogle.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=\ngoogle.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=\ngoogle.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=\ngoogle.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=\ngoogle.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=\ngoogle.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=\ngoogle.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=\ngoogle.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=\ngoogle.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=\ngoogle.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=\ngoogle.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=\ngoogle.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=\ngoogle.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=\ngoogle.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=\ngoogle.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=\ngoogle.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=\ngopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=\ngopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=\ngopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=\ngopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=\ngopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=\ngopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=\ngopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=\ngopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=\ngopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\nhonnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=\nsigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=\nsourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=\n"
  },
  {
    "path": "recipes/mapping/.gitignore",
    "content": "/mapping\n"
  },
  {
    "path": "recipes/mapping/mapping.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Connect creates an index with a mapping with different data types.\n//\n// Example\n//\n//     mapping -url=http://127.0.0.1:9200 -index=twitter\n//\npackage main\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"log\"\n\t\"time\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nconst (\n\tmapping = `\n\t{\n\t\t\"settings\":{\n\t\t\t\"number_of_shards\": {{.NumberOfShards}},\n\t\t\t\"number_of_replicas\": {{.NumberOfReplicas}}\n\t\t},\n\t\t\"mappings\":{\n\t\t\t\"properties\":{\n\t\t\t\t\"user\":{\n\t\t\t\t\t\"type\":\"keyword\"\n\t\t\t\t},\n\t\t\t\t\"message\":{\n\t\t\t\t\t\"type\":\"text\"\n\t\t\t\t},\n\t\t\t\t\"retweets\":{\n\t\t\t\t\t\"type\":\"integer\"\n\t\t\t\t},\n\t\t\t\t\"created\":{\n\t\t\t\t\t\"type\":\"date\"\n\t\t\t\t},\n\t\t\t\t\"attributes\":{\n\t\t\t\t\t\"type\":\"object\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t`\n)\n\n// Tweet is just an example document.\ntype Tweet struct {\n\tUser     string                 `json:\"user\"`\n\tMessage  string                 `json:\"message\"`\n\tRetweets int                    `json:\"retweets\"`\n\tCreated  time.Time              `json:\"created\"`\n\tAttrs    map[string]interface{} `json:\"attributes,omitempty\"`\n}\n\nfunc main() {\n\tvar (\n\t\turl      = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tsniff    = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t\tindex    = flag.String(\"index\", \"\", \"Index name\")\n\t\tshards   = flag.Int(\"shards\", 1, \"Number of shards\")\n\t\treplicas = flag.Int(\"replicas\", 0, \"Number of replicas\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\t*url = \"http://127.0.0.1:9200\"\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"please specify an index name -index\")\n\t}\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(elastic.SetURL(*url), elastic.SetSniff(*sniff))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t_ = client\n\n\t// Check if index already exists. We'll drop it then.\n\t// Next, we create a fresh index/mapping.\n\tctx := context.Background()\n\texists, err := client.IndexExists(*index).Do(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif exists {\n\t\t_, err := client.DeleteIndex(*index).Do(ctx)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\n\t// Dynamically create the index with the specified number of shards/replicas\n\ttmpl, err := template.New(\"T\").Parse(mapping)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tvar body bytes.Buffer\n\terr = tmpl.ExecuteTemplate(&body, \"T\", struct {\n\t\tNumberOfShards   int\n\t\tNumberOfReplicas int\n\t}{\n\t\tNumberOfShards:   *shards,\n\t\tNumberOfReplicas: *replicas,\n\t})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t_, err = client.CreateIndex(*index).BodyString(body.String()).Do(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Add a tweet\n\t{\n\t\ttweet := Tweet{\n\t\t\tUser:     \"olivere\",\n\t\t\tMessage:  \"Welcome to Go and Elasticsearch.\",\n\t\t\tRetweets: 0,\n\t\t\tCreated:  time.Now(),\n\t\t\tAttrs: map[string]interface{}{\n\t\t\t\t\"views\": 17,\n\t\t\t\t\"vip\":   true,\n\t\t\t},\n\t\t}\n\t\t_, err := client.Index().\n\t\t\tIndex(*index).\n\t\t\tId(\"1\").\n\t\t\tBodyJson(&tweet).\n\t\t\tRefresh(\"true\").\n\t\t\tDo(context.TODO())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\n\t// Read the tweet\n\t{\n\t\tdoc, err := client.Get().\n\t\t\tIndex(*index).\n\t\t\tId(\"1\").\n\t\t\tDo(context.TODO())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tvar tweet Tweet\n\t\tif err = json.Unmarshal(doc.Source, &tweet); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"%s at %s: %s (%d retweets)\\n\",\n\t\t\ttweet.User,\n\t\t\ttweet.Created,\n\t\t\ttweet.Message,\n\t\t\ttweet.Retweets,\n\t\t)\n\t\tfmt.Printf(\"  %v\\n\", tweet.Attrs)\n\t}\n}\n"
  },
  {
    "path": "recipes/middleware/.gitignore",
    "content": "/middleware\n"
  },
  {
    "path": "recipes/middleware/main.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Middleware via HTTP RoundTripper.\n//\n// Example\n//\n//     middleware \"http://127.0.0.1:9200/test-index?sniff=false&healthcheck=false\"\n//\npackage main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"sync/atomic\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\n// CountingTransport will count requests.\ntype CountingTransport struct {\n\tN    int64             // number of requests passing this transport\n\tnext http.RoundTripper // next round-tripper or http.DefaultTransport if nil\n}\n\n// RoundTrip implements a transport that will count requests.\nfunc (tr *CountingTransport) RoundTrip(r *http.Request) (*http.Response, error) {\n\tatomic.AddInt64(&tr.N, 1)\n\tif tr.next != nil {\n\t\treturn tr.next.RoundTrip(r)\n\t}\n\treturn http.DefaultTransport.RoundTrip(r)\n}\n\nfunc main() {\n\tvar (\n\t\turl   = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tsniff = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\t*url = \"http://127.0.0.1:9200\"\n\t}\n\n\ttr := &CountingTransport{}\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(*url),\n\t\telastic.SetSniff(*sniff),\n\t\telastic.SetHttpClient(&http.Client{\n\t\t\tTransport: tr,\n\t\t}),\n\t)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Get ES version\n\tindices, err := client.IndexNames()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfor _, index := range indices {\n\t\tfmt.Println(index)\n\t}\n\n\t// Just a status message\n\tfmt.Printf(\"%d requests executed.\\n\", tr.N)\n}\n"
  },
  {
    "path": "recipes/scroll/.gitignore",
    "content": "/scroll\n"
  },
  {
    "path": "recipes/scroll/scroll.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Scroll illustrates scrolling through a set of documents.\n//\n// Example\n//\n// Scroll through an index called \"products\".\n// Use \"_uid\" as the default field:\n//\n//     scroll -index=products -size=100\n//\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc main() {\n\tvar (\n\t\turl   = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tindex = flag.String(\"index\", \"\", \"Elasticsearch index name\")\n\t\tsize  = flag.Int(\"size\", 100, \"Slice of documents to get per scroll\")\n\t\tsniff = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\tlog.Fatal(\"missing url parameter\")\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"missing index parameter\")\n\t}\n\tif *size <= 0 {\n\t\tlog.Fatal(\"size must be greater than zero\")\n\t}\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(elastic.SetURL(*url), elastic.SetSniff(*sniff))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Setup a group of goroutines from the excellent errgroup package\n\tg, ctx := errgroup.WithContext(context.TODO())\n\n\t// Hits channel will be sent to from the first set of goroutines and consumed by the second\n\ttype hit struct {\n\t\tSlice int\n\t\tHit   elastic.SearchHit\n\t}\n\thitsc := make(chan hit)\n\n\tbegin := time.Now()\n\n\t// Start goroutine for this sliced scroll\n\tg.Go(func() error {\n\t\tdefer close(hitsc)\n\n\t\t// Prepare the query\n\t\tvar query elastic.Query\n\t\tquery = elastic.NewMatchAllQuery()\n\t\tsvc := client.Scroll(*index).Query(query)\n\t\tfor {\n\t\t\tres, err := svc.Do(ctx)\n\t\t\tif err == io.EOF {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tfor _, searchHit := range res.Hits.Hits {\n\t\t\t\t// Pass the hit to the hits channel, which will be consumed below\n\t\t\t\tselect {\n\t\t\t\tcase hitsc <- hit{Hit: *searchHit}:\n\t\t\t\tcase <-ctx.Done():\n\t\t\t\t\treturn ctx.Err()\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Second goroutine will consume the hits sent from the workers in first set of goroutines\n\tvar total uint64\n\tg.Go(func() error {\n\t\tfor range hitsc {\n\t\t\t// We simply count the hits here.\n\t\t\tcurrent := atomic.AddUint64(&total, 1)\n\t\t\tsec := int(time.Since(begin).Seconds())\n\t\t\tfmt.Printf(\"%8d | %02d:%02d\\r\", current, sec/60, sec%60)\n\t\t\tselect {\n\t\t\tdefault:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Wait until all goroutines are finished\n\tif err := g.Wait(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Printf(\"Scrolled through a total of %d documents in %v\\n\", total, time.Since(begin))\n}\n"
  },
  {
    "path": "recipes/search_with_point_in_time/.gitignore",
    "content": "/search_with_point_in_time\n"
  },
  {
    "path": "recipes/search_with_point_in_time/search.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Search illustrates how to search using the Point in Time API.\n//\n// Example\n//\n// Scroll through an index called \"products\".\n//\n//     ./search_with_point_in_time -index=products -size=100\n//\n// If you don't have an index, use the \"populate\" command to fill one.\n//\n//     ./search_with_point_in_time -index=products populate\n//\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc main() {\n\tvar (\n\t\turl   = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tindex = flag.String(\"index\", \"\", \"Elasticsearch index name\")\n\t\tsize  = flag.Int(\"size\", 10, \"Slice of documents to get per scroll\")\n\t\tsniff = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\tlog.Fatal(\"missing url parameter\")\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"missing index parameter\")\n\t}\n\tif *size <= 0 {\n\t\tlog.Fatal(\"size must be greater than zero\")\n\t}\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(elastic.SetURL(*url), elastic.SetSniff(*sniff))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Use \"search ... populate\" to populate the index with random data\n\tif flag.Arg(0) == \"populate\" {\n\t\tif err := populate(client, *index); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\treturn\n\t}\n\n\t// Open a Point in Time\n\tpit, err := client.OpenPointInTime(*index).KeepAlive(\"2m\").Do(context.Background())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Notice that at this point we could even delete the documents\n\t// from the index: The Point in Time will make sure that we still\n\t// get the results when the Point in Time has been created.\n\t//\n\t// Notice that you must not pass an index, a routing, or a preference\n\t// to the Search API: Those values are taken from the Point in Time.\n\tres, err := client.Search().\n\t\tQuery(\n\t\t\t// Return random results\n\t\t\telastic.NewFunctionScoreQuery().AddScoreFunc(elastic.NewRandomFunction()),\n\t\t).\n\t\tSize(*size).\n\t\tPointInTime(\n\t\t\telastic.NewPointInTimeWithKeepAlive(pit.Id, \"2m\"),\n\t\t).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tfor _, hit := range res.Hits.Hits {\n\t\tvar doc map[string]interface{}\n\t\tif err := json.Unmarshal(hit.Source, &doc); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"%v\\n\", doc)\n\t}\n}\n\n// populate will fill an example index.\nfunc populate(client *elastic.Client, indexName string) error {\n\tbulk := client.Bulk().Index(indexName)\n\tfor i := 0; i < 10000; i++ {\n\t\tdoc := map[string]interface{}{\n\t\t\t\"name\": fmt.Sprintf(\"Product %d\", i+1),\n\t\t}\n\t\tbulk = bulk.Add(elastic.NewBulkIndexRequest().\n\t\t\tId(fmt.Sprint(i)).\n\t\t\tDoc(doc),\n\t\t)\n\t\tif bulk.NumberOfActions() >= 100 {\n\t\t\t_, err := bulk.Do(context.Background())\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t// bulk is reset after Do, so you can reuse it\n\t\t\t// We ignore indexing errors here though!\n\t\t}\n\t}\n\tif bulk.NumberOfActions() > 0 {\n\t\t_, err := bulk.Do(context.Background())\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n"
  },
  {
    "path": "recipes/sliced_scroll/.gitignore",
    "content": "/sliced_scroll\n"
  },
  {
    "path": "recipes/sliced_scroll/sliced_scroll.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// SlicedScroll illustrates scrolling through a set of documents\n// in parallel. It uses the sliced scrolling feature introduced\n// in Elasticsearch 5.0 to create a number of Goroutines, each\n// scrolling through a slice of the total results. A second goroutine\n// receives the hits from the set of goroutines scrolling through\n// the slices and simply counts the total number and the number of\n// documents received per slice.\n//\n// The speedup of sliced scrolling can be significant but is very\n// dependent on the specific use case.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-scroll.html#sliced-scroll\n// for details on sliced scrolling in Elasticsearch.\n//\n// Example\n//\n// Scroll with 4 parallel slices through an index called \"products\".\n// Use \"_uid\" as the default field:\n//\n//     sliced_scroll -index=products -n=4\n//\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc main() {\n\tvar (\n\t\turl       = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tindex     = flag.String(\"index\", \"\", \"Elasticsearch index name\")\n\t\tfield     = flag.String(\"field\", \"\", \"Slice field (must be numeric)\")\n\t\tnumSlices = flag.Int(\"n\", 2, \"Number of slices to use in parallel\")\n\t\tsniff     = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\tlog.Fatal(\"missing url parameter\")\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"missing index parameter\")\n\t}\n\tif *numSlices <= 0 {\n\t\tlog.Fatal(\"n must be greater than zero\")\n\t}\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(elastic.SetURL(*url), elastic.SetSniff(*sniff))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Setup a group of goroutines from the excellent errgroup package\n\tg, ctx := errgroup.WithContext(context.TODO())\n\n\t// Hits channel will be sent to from the first set of goroutines and consumed by the second\n\ttype hit struct {\n\t\tSlice int\n\t\tHit   elastic.SearchHit\n\t}\n\thitsc := make(chan hit)\n\n\tbegin := time.Now()\n\n\t// Start a number of goroutines to parallelize scrolling\n\tvar wg sync.WaitGroup\n\tfor i := 0; i < *numSlices; i++ {\n\t\twg.Add(1)\n\n\t\tslice := i\n\n\t\t// Prepare the query\n\t\tvar query elastic.Query\n\t\tquery = elastic.NewMatchAllQuery()\n\n\t\t// Prepare the slice\n\t\tsliceQuery := elastic.NewSliceQuery().Id(i).Max(*numSlices)\n\t\tif *field != \"\" {\n\t\t\tsliceQuery = sliceQuery.Field(*field)\n\t\t}\n\n\t\t// Start goroutine for this sliced scroll\n\t\tg.Go(func() error {\n\t\t\tdefer wg.Done()\n\t\t\tsvc := client.Scroll(*index).Query(query).Slice(sliceQuery)\n\t\t\tfor {\n\t\t\t\tres, err := svc.Do(ctx)\n\t\t\t\tif err == io.EOF {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tfor _, searchHit := range res.Hits.Hits {\n\t\t\t\t\t// Pass the hit to the hits channel, which will be consumed below\n\t\t\t\t\tselect {\n\t\t\t\t\tcase hitsc <- hit{Slice: slice, Hit: *searchHit}:\n\t\t\t\t\tcase <-ctx.Done():\n\t\t\t\t\t\treturn ctx.Err()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\tgo func() {\n\t\t// Wait until all scrolling is done\n\t\twg.Wait()\n\t\tclose(hitsc)\n\t}()\n\n\t// Second goroutine will consume the hits sent from the workers in first set of goroutines\n\tvar total uint64\n\ttotals := make([]uint64, *numSlices)\n\tg.Go(func() error {\n\t\tfor hit := range hitsc {\n\t\t\t// We simply count the hits here.\n\t\t\tatomic.AddUint64(&totals[hit.Slice], 1)\n\t\t\tcurrent := atomic.AddUint64(&total, 1)\n\t\t\tsec := int(time.Since(begin).Seconds())\n\t\t\tfmt.Printf(\"%8d | %02d:%02d\\r\", current, sec/60, sec%60)\n\t\t\tselect {\n\t\t\tdefault:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Wait until all goroutines are finished\n\tif err := g.Wait(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Printf(\"Scrolled through a total of %d documents in %v\\n\", total, time.Since(begin))\n\tfor i := 0; i < *numSlices; i++ {\n\t\tfmt.Printf(\"Slice %2d received %d documents\\n\", i, totals[i])\n\t}\n}\n"
  },
  {
    "path": "recipes/suggesters/completion/.gitignore",
    "content": "/completion\n"
  },
  {
    "path": "recipes/suggesters/completion/main.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Connect creates an index with a mapping with different data types.\n//\n// Example\n//\n//\n//     ./completion -url=http://127.0.0.1:9200 -index=cities\n//\n// For more details and experimentation, take a look at the official\n// documentation at https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-completion.html.\npackage main\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nconst (\n\tmapping = `\n\t{\n\t\t\"settings\":{\n\t\t\t\"number_of_shards\":1,\n\t\t\t\"number_of_replicas\":0\n\t\t},\n\t\t\"mappings\":{\n\t\t\t\"properties\":{\n\t\t\t\t\"name\":{\n\t\t\t\t\t\"type\":\"keyword\"\n\t\t\t\t},\n\t\t\t\t\"name_suggest\":{\n\t\t\t\t\t\"type\":\"completion\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t`\n)\n\n// City is used in this example as an index document for suggestions.\ntype City struct {\n\tName        string                `json:\"name,omitempty\"`\n\tNameSuggest *elastic.SuggestField `json:\"name_suggest,omitempty\"`\n}\n\nvar (\n\tcities = []string{\n\t\t\"Amsterdam\",\n\t\t\"Athens\",\n\t\t\"Berlin\",\n\t\t\"Barcelona\",\n\t\t\"Brussels\",\n\t\t\"Dublin\",\n\t\t\"Helsinki\",\n\t\t\"Madrid\",\n\t\t\"Lisbon\",\n\t\t\"London\",\n\t\t\"Oslo\",\n\t\t\"Paris\",\n\t\t\"Stockholm\",\n\t\t\"Rome\",\n\t\t\"Valletta\",\n\t\t\"Vienna\",\n\t}\n)\n\nfunc main() {\n\tvar (\n\t\turl   = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tsniff = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t\tindex = flag.String(\"index\", \"\", \"Index name\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\t*url = \"http://127.0.0.1:9200\"\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"please specify an index name -index\")\n\t}\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(*url),\n\t\telastic.SetSniff(*sniff),\n\t\t// elastic.SetTraceLog(log.New(os.Stdout, \"\", 0)), // uncomment to see the wire protocol\n\t)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\t_ = client\n\n\t// Check if index already exists. We'll drop it then.\n\t// Next, we create a fresh index/mapping.\n\tctx := context.Background()\n\texists, err := client.IndexExists(*index).Do(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif exists {\n\t\t_, err := client.DeleteIndex(*index).Do(ctx)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\t_, err = client.CreateIndex(*index).Body(mapping).Do(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Add some cities\n\tfor _, name := range cities {\n\t\tfmt.Printf(\"Add %s...\\n\", name)\n\t\t_, err := client.Index().\n\t\t\tIndex(*index).\n\t\t\tBodyJson(&City{\n\t\t\t\tName:        name,\n\t\t\t\tNameSuggest: elastic.NewSuggestField(name),\n\t\t\t}).\n\t\t\tRefresh(\"true\").\n\t\t\tDo(context.Background())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\n\t// Allow suggestions\n\treader := bufio.NewReader(os.Stdin)\n\tfor {\n\t\tfmt.Print(\"Enter a city name: \")\n\t\tname, _ := reader.ReadString('\\n')\n\t\tname = strings.TrimRight(name, \"\\n\")\n\t\tif name == \"\" {\n\t\t\tbreak\n\t\t}\n\n\t\tres, err := client.Search().\n\t\t\tIndex(*index).\n\t\t\tSuggester(\n\t\t\t\telastic.NewCompletionSuggester(\"name_suggestion\").\n\t\t\t\t\tField(\"name_suggest\").\n\t\t\t\t\tText(name),\n\t\t\t).\n\t\t\tSize(0). // we dont' want the hits, just the suggestions\n\t\t\tPretty(true).\n\t\t\tDo(context.Background())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tsuggestions, found := res.Suggest[\"name_suggestion\"]\n\t\tif !found {\n\t\t\tfmt.Printf(\"%d matches found:\\n\", 0)\n\t\t\tcontinue\n\t\t}\n\t\tfor _, suggestion := range suggestions {\n\t\t\tfmt.Printf(\"%d suggestions found for text %q:\\n\", len(suggestion.Options), suggestion.Text)\n\t\t\tfor _, opt := range suggestion.Options {\n\t\t\t\tfmt.Printf(\"* %s\\n\", opt.Text)\n\n\t\t\t\t// The document's source is in opt.Source\n\t\t\t\tvar city City\n\t\t\t\tif err = json.Unmarshal(opt.Source, &city); err != nil {\n\t\t\t\t\tlog.Fatal(err)\n\t\t\t\t}\n\t\t\t\t_ = city\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "recipes/text_vs_keyword/.gitignore",
    "content": "/text_vs_keyword\n"
  },
  {
    "path": "recipes/text_vs_keyword/main.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Connect illustrates exact matches vs fulltext queries with\n// \"text\" and \"keyword\" types and Get as well as Term- and Match Query.\n//\n// Example\n//\n//     go run main.go -url=http://127.0.0.1:9200 -index=testindex\n//     go run main.go -url=http://127.0.0.1:9200 -index=test -trace\n//\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nconst (\n\tmapping = `\n\t{\n\t\t\"settings\":{\n\t\t\t\"number_of_shards\":1,\n\t\t\t\"number_of_replicas\":0\n\t\t},\n\t\t\"mappings\":{\n\t\t\t\"properties\":{\n\t\t\t\t\"user\":{\n\t\t\t\t\t\"type\":\"keyword\"\n\t\t\t\t},\n\t\t\t\t\"title\":{\n\t\t\t\t\t\"type\":\"text\",\n\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\"keyword\": {\n\t\t\t\t\t\t\t\"type\": \"keyword\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t`\n)\n\n// Doc is just an example document.\ntype Doc struct {\n\tID    string `json:\"-\"` // we use it as an ID\n\tUser  string `json:\"user\"`\n\tTitle string `json:\"title\"`\n}\n\nfunc main() {\n\tvar (\n\t\turl   = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tsniff = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t\tindex = flag.String(\"index\", \"\", \"Index name\")\n\t\ttrace = flag.Bool(\"trace\", false, \"Enable or disable trace output\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\n\tif *url == \"\" {\n\t\t*url = \"http://127.0.0.1:9200\"\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"please specify an index name -index\")\n\t}\n\n\t// Create an Elasticsearch client\n\toptions := []elastic.ClientOptionFunc{\n\t\telastic.SetURL(*url),\n\t\telastic.SetSniff(*sniff),\n\t}\n\tif *trace {\n\t\toptions = append(options, elastic.SetTraceLog(\n\t\t\tlog.New(os.Stdout, \"\", 0),\n\t\t))\n\t}\n\tclient, err := elastic.NewClient(options...)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Check if index already exists. We'll drop it then.\n\t// Next, we create a fresh index/mapping.\n\tctx := context.Background()\n\texists, err := client.IndexExists(*index).Do(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tif exists {\n\t\t_, err := client.DeleteIndex(*index).Do(ctx)\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}\n\t_, err = client.CreateIndex(*index).Body(mapping).Do(ctx)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Add some documents\n\n\t{\n\t\tdocs := []Doc{\n\t\t\t{\n\t\t\t\tID:    \"one\",\n\t\t\t\tUser:  \"olivere\",\n\t\t\t\tTitle: \"Go and Elasticsearch.\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tID:    \"two\",\n\t\t\t\tUser:  \"pepper\",\n\t\t\t\tTitle: \"Amsterdam is nice.\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tID:    \"three\",\n\t\t\t\tUser:  \"salt\",\n\t\t\t\tTitle: \"So is Barcelona.\",\n\t\t\t},\n\t\t}\n\t\tfor _, doc := range docs {\n\t\t\t_, err := client.Index().\n\t\t\t\tIndex(*index).\n\t\t\t\tId(doc.ID).\n\t\t\t\tBodyJson(doc).\n\t\t\t\tRefresh(\"true\").\n\t\t\t\tDo(context.TODO())\n\t\t\tif err != nil {\n\t\t\t\tlog.Fatal(err)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Read a document by ID. This isn't searching, but looking\n\t// up a document by its unique identifier. Same with MultiGet.\n\t{\n\t\tsrc, err := client.Get().\n\t\t\tIndex(*index).\n\t\t\tId(\"one\").\n\t\t\tDo(context.TODO())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tvar doc Doc\n\t\tif err = json.Unmarshal(src.Source, &doc); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"%s: %s\\n\",\n\t\t\tdoc.User,\n\t\t\tdoc.Title,\n\t\t)\n\t}\n\n\t// Read a document by exact query on keyword field\n\t// It will find the document because \"user\" is of type \"keyword\"\n\t// and there will be an exact match on the value of \"salt\".\n\t{\n\t\tresp, err := client.Search().\n\t\t\tIndex(*index).\n\t\t\tQuery(elastic.NewTermQuery(\"user\", \"salt\")).\n\t\t\tDo(context.TODO())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif want, have := int64(1), resp.TotalHits(); want != have {\n\t\t\tlog.Fatalf(\"expected %d hits, got %d\", want, have)\n\t\t}\n\t\tvar doc Doc\n\t\tif err = json.Unmarshal(resp.Hits.Hits[0].Source, &doc); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"%s: %s\\n\",\n\t\t\tdoc.User,\n\t\t\tdoc.Title,\n\t\t)\n\t}\n\n\t// Search for documents by \"fulltext\" query on text field.\n\t// This works fine because the MatchQuery will match on \"Amsterdam\".\n\t// Notice that the full title of the found document is \"Amsterdam is nice.\",\n\t// so an exact query on the \"title\" field for \"Amsterdam\" wouldn't find anything.\n\t{\n\t\tresp, err := client.Search().\n\t\t\tIndex(*index).\n\t\t\tQuery(elastic.NewMatchQuery(\"title\", \"Amsterdam\")).\n\t\t\tDo(context.TODO())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif want, have := int64(1), resp.TotalHits(); want != have {\n\t\t\tlog.Fatalf(\"expected %d hits, got %d\", want, have)\n\t\t}\n\t\tvar doc Doc\n\t\tif err = json.Unmarshal(resp.Hits.Hits[0].Source, &doc); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"%s: %s\\n\",\n\t\t\tdoc.User,\n\t\t\tdoc.Title,\n\t\t)\n\t}\n\n\t// Search for documents by exact query on text field. This case will fail,\n\t// because \"title\" is a field of type \"text\", and there is no exact match\n\t// for the term \"Amsterdam\" on any \"title\" field.\n\t{\n\t\tresp, err := client.Search().\n\t\t\tIndex(*index).\n\t\t\tQuery(elastic.NewTermQuery(\"title\", \"Amsterdam\")).\n\t\t\tDo(context.TODO())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif want, have := int64(0), resp.TotalHits(); want != have {\n\t\t\tlog.Fatalf(\"expected %d hits, got %d\", want, have)\n\t\t}\n\t}\n\n\t// Notice how this works again. We now search for an exact match by\n\t// using \"title.keyword\", a multi-field. Notice that we can only find\n\t// the exact match if we use \"Amsterdam is nice.\". Using the term\n\t// \"Amsterdam\" would yield no result, again. Doing a match query for\n\t// \"Amsterdam is nice.\" will yield two results BTW, because there is\n\t// a match for the word \"is\" in \"So is Barcelona.\" as well (albeit with\n\t// a significantly lower score).\n\t{\n\t\tresp, err := client.Search().\n\t\t\tIndex(*index).\n\t\t\tQuery(elastic.NewMatchQuery(\"title.keyword\", \"Amsterdam is nice.\")).\n\t\t\tDo(context.TODO())\n\t\tif err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tif want, have := int64(1), resp.TotalHits(); want != have {\n\t\t\tlog.Fatalf(\"expected %d hits, got %d\", want, have)\n\t\t}\n\t\tvar doc Doc\n\t\tif err = json.Unmarshal(resp.Hits.Hits[0].Source, &doc); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\tfmt.Printf(\"%s: %s\\n\",\n\t\t\tdoc.User,\n\t\t\tdoc.Title,\n\t\t)\n\t}\n}\n"
  },
  {
    "path": "recipes/tracing/.gitignore",
    "content": "/tracing\n"
  },
  {
    "path": "recipes/tracing/README.md",
    "content": "# Illustrate Elastic OpenTracing\n\nRun Jaeger (any other supported tracers work of course):\n\n```sh\n./run-tracer.sh\n```\n\nThen open the web UI:\n\n```sh\nopen http://localhost:16686\n```\n\nThen run the example, e.g.:\n\n```sh\ngo build\n./tracing -index=test -type=doc -n=100000 -bulk-size=100\n```\n"
  },
  {
    "path": "recipes/tracing/otel/.gitignore",
    "content": "/tracing\n"
  },
  {
    "path": "recipes/tracing/otel/README.md",
    "content": "# Tracing with OpenTelemetry\n\nRun Jaeger (any other supported tracers work of course):\n\n```sh\n./run-tracer.sh\n```\n\nThen open the web UI:\n\n```sh\nopen http://localhost:16686\n```\n\nThen run the example, e.g.:\n\n```sh\ngo build\n./tracing -index=test -type=doc -n=100000 -bulk-size=100\n```\n"
  },
  {
    "path": "recipes/tracing/otel/run-tracer.sh",
    "content": "#!/bin/sh\ndocker run -d --name jaeger \\\n  -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \\\n  -p 5775:5775/udp \\\n  -p 6831:6831/udp \\\n  -p 6832:6832/udp \\\n  -p 5778:5778 \\\n  -p 16686:16686 \\\n  -p 14268:14268 \\\n  -p 9411:9411 \\\n  jaegertracing/all-in-one:latest\n"
  },
  {
    "path": "recipes/tracing/otel/tracing.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Tracing is the same as the bulk_insert recipe, but adds\n// OpenTracing support.\n//\n// Example\n//\n// Bulk index 100.000 documents into the index \"warehouse\", type \"product\",\n// committing every set of 1.000 documents.\n//\n//     ./run-tracer.sh\n//     ./tracing -index=warehouse -type=product -n=100000 -bulk-size=1000\n//\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"golang.org/x/sync/errgroup\"\n\n\t\"go.opentelemetry.io/otel\"\n\t\"go.opentelemetry.io/otel/exporters/jaeger\"\n\t\"go.opentelemetry.io/otel/sdk/resource\"\n\ttracesdk \"go.opentelemetry.io/otel/sdk/trace\"\n\tsemconv \"go.opentelemetry.io/otel/semconv/v1.7.0\"\n\n\t\"github.com/olivere/elastic/v7\"\n\t\"github.com/olivere/elastic/v7/trace/opentelemetry\"\n)\n\nfunc main() {\n\tvar (\n\t\turl      = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tindex    = flag.String(\"index\", \"\", \"Elasticsearch index name\")\n\t\ttyp      = flag.String(\"type\", \"\", \"Elasticsearch type name\")\n\t\tsniff    = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t\tn        = flag.Int(\"n\", 0, \"Number of documents to bulk insert\")\n\t\tbulkSize = flag.Int(\"bulk-size\", 0, \"Number of documents to collect before committing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\trand.Seed(time.Now().UnixNano())\n\n\tif *url == \"\" {\n\t\tlog.Fatal(\"missing url parameter\")\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"missing index parameter\")\n\t}\n\tif *typ == \"\" {\n\t\tlog.Fatal(\"missing type parameter\")\n\t}\n\tif *n <= 0 {\n\t\tlog.Fatal(\"n must be a positive number\")\n\t}\n\tif *bulkSize <= 0 {\n\t\tlog.Fatal(\"bulk-size must be a positive number\")\n\t}\n\n\topts := []elastic.ClientOptionFunc{\n\t\telastic.SetURL(*url),\n\t\telastic.SetSniff(*sniff),\n\t}\n\n\t// Initialize Jaeger tracing\n\texp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(\"http://localhost:14268/api/traces\")))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\ttp := tracesdk.NewTraceProvider(\n\t\ttracesdk.WithBatcher(exp),\n\t\ttracesdk.WithResource(resource.NewWithAttributes(\n\t\t\tsemconv.ServiceNameKey.String(\"elastic-tracing\"),\n\t\t)),\n\t)\n\tdefer func() {\n\t\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\t\tdefer cancel()\n\t\tif err := tp.Shutdown(ctx); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t}()\n\totel.SetTracerProvider(tp)\n\n\thttpClient := &http.Client{\n\t\tTransport: opentelemetry.NewTransport(),\n\t}\n\topts = append(opts, elastic.SetHttpClient(httpClient))\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(opts...)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Setup a group of goroutines from the excellent errgroup package\n\tg, ctx := errgroup.WithContext(context.TODO())\n\n\t// The first goroutine will emit documents and send it to the second goroutine\n\t// via the docsc channel.\n\t// The second Goroutine will simply bulk insert the documents.\n\ttype doc struct {\n\t\tID        string    `json:\"id\"`\n\t\tTimestamp time.Time `json:\"@timestamp\"`\n\t}\n\tdocsc := make(chan doc)\n\n\tbegin := time.Now()\n\n\t// Goroutine to create documents\n\tg.Go(func() error {\n\t\tdefer close(docsc)\n\n\t\tbuf := make([]byte, 32)\n\t\tfor i := 0; i < *n; i++ {\n\t\t\t// Generate a random ID\n\t\t\t_, err := rand.Read(buf)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tid := base64.URLEncoding.EncodeToString(buf)\n\n\t\t\t// Construct the document\n\t\t\td := doc{\n\t\t\t\tID:        id,\n\t\t\t\tTimestamp: time.Now(),\n\t\t\t}\n\n\t\t\t// Send over to 2nd goroutine, or cancel\n\t\t\tselect {\n\t\t\tcase docsc <- d:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Second goroutine will consume the documents sent from the first and bulk insert into ES\n\tvar total uint64\n\tg.Go(func() error {\n\t\tbulk := client.Bulk().Index(*index).Type(*typ)\n\t\tfor d := range docsc {\n\t\t\t// Simple progress\n\t\t\tcurrent := atomic.AddUint64(&total, 1)\n\t\t\tdur := time.Since(begin).Seconds()\n\t\t\tsec := int(dur)\n\t\t\tpps := int64(float64(current) / dur)\n\t\t\tfmt.Printf(\"%10d | %6d req/s | %02d:%02d\\r\", current, pps, sec/60, sec%60)\n\n\t\t\t// Enqueue the document\n\t\t\tbulk.Add(elastic.NewBulkIndexRequest().Id(d.ID).Doc(d))\n\t\t\tif bulk.NumberOfActions() >= *bulkSize {\n\t\t\t\t// Commit\n\t\t\t\tres, err := bulk.Do(ctx)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif res.Errors {\n\t\t\t\t\t// Look up the failed documents with res.Failed(), and e.g. recommit\n\t\t\t\t\treturn errors.New(\"bulk commit failed\")\n\t\t\t\t}\n\t\t\t\t// \"bulk\" is reset after Do, so you can reuse it\n\t\t\t}\n\n\t\t\tselect {\n\t\t\tdefault:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\t\t}\n\n\t\t// Commit the final batch before exiting\n\t\tif bulk.NumberOfActions() > 0 {\n\t\t\t_, err = bulk.Do(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Wait until all goroutines are finished\n\tif err := g.Wait(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Final results\n\tdur := time.Since(begin).Seconds()\n\tsec := int(dur)\n\tpps := int64(float64(total) / dur)\n\tfmt.Printf(\"%10d | %6d req/s | %02d:%02d\\n\", total, pps, sec/60, sec%60)\n}\n"
  },
  {
    "path": "recipes/tracing/run-tracer.sh",
    "content": "#!/bin/sh\ndocker run -d --name jaeger \\\n  -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \\\n  -p 5775:5775/udp \\\n  -p 6831:6831/udp \\\n  -p 6832:6832/udp \\\n  -p 5778:5778 \\\n  -p 16686:16686 \\\n  -p 14268:14268 \\\n  -p 9411:9411 \\\n  jaegertracing/all-in-one:latest\n"
  },
  {
    "path": "recipes/tracing/tracing.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// Tracing is the same as the bulk_insert recipe, but adds\n// OpenTracing support.\n//\n// Example\n//\n// Bulk index 100.000 documents into the index \"warehouse\", type \"product\",\n// committing every set of 1.000 documents.\n//\n//     ./run-tracer.sh\n//     ./tracing -index=warehouse -type=product -n=100000 -bulk-size=1000\n//\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\tjaegerconfig \"github.com/uber/jaeger-client-go/config\"\n\tjaegerlog \"github.com/uber/jaeger-client-go/log\"\n\tjaegerexpvar \"github.com/uber/jaeger-lib/metrics/expvar\"\n\t\"golang.org/x/sync/errgroup\"\n\n\t\"github.com/olivere/elastic/v7\"\n\t\"github.com/olivere/elastic/v7/trace/opentracing\"\n)\n\nfunc main() {\n\tvar (\n\t\turl      = flag.String(\"url\", \"http://localhost:9200\", \"Elasticsearch URL\")\n\t\tindex    = flag.String(\"index\", \"\", \"Elasticsearch index name\")\n\t\ttyp      = flag.String(\"type\", \"\", \"Elasticsearch type name\")\n\t\tsniff    = flag.Bool(\"sniff\", true, \"Enable or disable sniffing\")\n\t\tn        = flag.Int(\"n\", 0, \"Number of documents to bulk insert\")\n\t\tbulkSize = flag.Int(\"bulk-size\", 0, \"Number of documents to collect before committing\")\n\t)\n\tflag.Parse()\n\tlog.SetFlags(0)\n\trand.Seed(time.Now().UnixNano())\n\n\tif *url == \"\" {\n\t\tlog.Fatal(\"missing url parameter\")\n\t}\n\tif *index == \"\" {\n\t\tlog.Fatal(\"missing index parameter\")\n\t}\n\tif *typ == \"\" {\n\t\tlog.Fatal(\"missing type parameter\")\n\t}\n\tif *n <= 0 {\n\t\tlog.Fatal(\"n must be a positive number\")\n\t}\n\tif *bulkSize <= 0 {\n\t\tlog.Fatal(\"bulk-size must be a positive number\")\n\t}\n\n\topts := []elastic.ClientOptionFunc{\n\t\telastic.SetURL(*url),\n\t\telastic.SetSniff(*sniff),\n\t}\n\n\t// Initialize Jaeger tracing\n\tcfg := jaegerconfig.Configuration{}\n\tcloser, err := cfg.InitGlobalTracer(\n\t\t\"elastic-tracing\",\n\t\tjaegerconfig.Logger(jaegerlog.StdLogger),\n\t\tjaegerconfig.Metrics(jaegerexpvar.NewFactory(10)),\n\t)\n\tif err != nil {\n\t\tlog.Fatalf(\"unable to initialize jaeger tracer: %v\", err)\n\t}\n\tdefer closer.Close()\n\n\thttpClient := &http.Client{\n\t\tTransport: opentracing.NewTransport(),\n\t}\n\topts = append(opts, elastic.SetHttpClient(httpClient))\n\n\t// Create an Elasticsearch client\n\tclient, err := elastic.NewClient(opts...)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Setup a group of goroutines from the excellent errgroup package\n\tg, ctx := errgroup.WithContext(context.TODO())\n\n\t// The first goroutine will emit documents and send it to the second goroutine\n\t// via the docsc channel.\n\t// The second Goroutine will simply bulk insert the documents.\n\ttype doc struct {\n\t\tID        string    `json:\"id\"`\n\t\tTimestamp time.Time `json:\"@timestamp\"`\n\t}\n\tdocsc := make(chan doc)\n\n\tbegin := time.Now()\n\n\t// Goroutine to create documents\n\tg.Go(func() error {\n\t\tdefer close(docsc)\n\n\t\tbuf := make([]byte, 32)\n\t\tfor i := 0; i < *n; i++ {\n\t\t\t// Generate a random ID\n\t\t\t_, err := rand.Read(buf)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tid := base64.URLEncoding.EncodeToString(buf)\n\n\t\t\t// Construct the document\n\t\t\td := doc{\n\t\t\t\tID:        id,\n\t\t\t\tTimestamp: time.Now(),\n\t\t\t}\n\n\t\t\t// Send over to 2nd goroutine, or cancel\n\t\t\tselect {\n\t\t\tcase docsc <- d:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Second goroutine will consume the documents sent from the first and bulk insert into ES\n\tvar total uint64\n\tg.Go(func() error {\n\t\tbulk := client.Bulk().Index(*index).Type(*typ)\n\t\tfor d := range docsc {\n\t\t\t// Simple progress\n\t\t\tcurrent := atomic.AddUint64(&total, 1)\n\t\t\tdur := time.Since(begin).Seconds()\n\t\t\tsec := int(dur)\n\t\t\tpps := int64(float64(current) / dur)\n\t\t\tfmt.Printf(\"%10d | %6d req/s | %02d:%02d\\r\", current, pps, sec/60, sec%60)\n\n\t\t\t// Enqueue the document\n\t\t\tbulk.Add(elastic.NewBulkIndexRequest().Id(d.ID).Doc(d))\n\t\t\tif bulk.NumberOfActions() >= *bulkSize {\n\t\t\t\t// Commit\n\t\t\t\tres, err := bulk.Do(ctx)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\tif res.Errors {\n\t\t\t\t\t// Look up the failed documents with res.Failed(), and e.g. recommit\n\t\t\t\t\treturn errors.New(\"bulk commit failed\")\n\t\t\t\t}\n\t\t\t\t// \"bulk\" is reset after Do, so you can reuse it\n\t\t\t}\n\n\t\t\tselect {\n\t\t\tdefault:\n\t\t\tcase <-ctx.Done():\n\t\t\t\treturn ctx.Err()\n\t\t\t}\n\t\t}\n\n\t\t// Commit the final batch before exiting\n\t\tif bulk.NumberOfActions() > 0 {\n\t\t\t_, err = bulk.Do(ctx)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t})\n\n\t// Wait until all goroutines are finished\n\tif err := g.Wait(); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Final results\n\tdur := time.Since(begin).Seconds()\n\tsec := int(dur)\n\tpps := int64(float64(total) / dur)\n\tfmt.Printf(\"%10d | %6d req/s | %02d:%02d\\n\", total, pps, sec/60, sec%60)\n}\n"
  },
  {
    "path": "reindex.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// ReindexService is a method to copy documents from one index to another.\n// It is documented at https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-reindex.html.\ntype ReindexService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trefresh             string\n\ttimeout             string\n\twaitForActiveShards string\n\twaitForCompletion   *bool\n\trequestsPerSecond   *int\n\tslices              interface{}\n\tbody                interface{}\n\tsource              *ReindexSource\n\tdestination         *ReindexDestination\n\tconflicts           string\n\tsize                *int\n\tscript              *Script\n}\n\n// NewReindexService creates a new ReindexService.\nfunc NewReindexService(client *Client) *ReindexService {\n\treturn &ReindexService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ReindexService) Pretty(pretty bool) *ReindexService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ReindexService) Human(human bool) *ReindexService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ReindexService) ErrorTrace(errorTrace bool) *ReindexService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ReindexService) FilterPath(filterPath ...string) *ReindexService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ReindexService) Header(name string, value string) *ReindexService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ReindexService) Headers(headers http.Header) *ReindexService {\n\ts.headers = headers\n\treturn s\n}\n\n// WaitForActiveShards sets the number of shard copies that must be active before\n// proceeding with the reindex operation. Defaults to 1, meaning the primary shard only.\n// Set to `all` for all shard copies, otherwise set to any non-negative value less than or\n// equal to the total number of copies for the shard (number of replicas + 1).\nfunc (s *ReindexService) WaitForActiveShards(waitForActiveShards string) *ReindexService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// RequestsPerSecond specifies the throttle to set on this request in sub-requests per second.\n// -1 means set no throttle as does \"unlimited\" which is the only non-float this accepts.\nfunc (s *ReindexService) RequestsPerSecond(requestsPerSecond int) *ReindexService {\n\ts.requestsPerSecond = &requestsPerSecond\n\treturn s\n}\n\n// Slices specifies the number of slices this task should be divided into. Defaults to 1.\n// It used to  be a number, but can be set to \"auto\" as of 6.7.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-reindex.html#docs-reindex-slice\n// for details.\nfunc (s *ReindexService) Slices(slices interface{}) *ReindexService {\n\ts.slices = slices\n\treturn s\n}\n\n// Refresh indicates whether Elasticsearch should refresh the effected indexes\n// immediately.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *ReindexService) Refresh(refresh string) *ReindexService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// Timeout is the time each individual bulk request should wait for shards\n// that are unavailable.\nfunc (s *ReindexService) Timeout(timeout string) *ReindexService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// WaitForCompletion indicates whether Elasticsearch should block until the\n// reindex is complete.\nfunc (s *ReindexService) WaitForCompletion(waitForCompletion bool) *ReindexService {\n\ts.waitForCompletion = &waitForCompletion\n\treturn s\n}\n\n// Source specifies the source of the reindexing process.\nfunc (s *ReindexService) Source(source *ReindexSource) *ReindexService {\n\ts.source = source\n\treturn s\n}\n\n// SourceIndex specifies the source index of the reindexing process.\nfunc (s *ReindexService) SourceIndex(index string) *ReindexService {\n\tif s.source == nil {\n\t\ts.source = NewReindexSource()\n\t}\n\ts.source = s.source.Index(index)\n\treturn s\n}\n\n// Destination specifies the destination of the reindexing process.\nfunc (s *ReindexService) Destination(destination *ReindexDestination) *ReindexService {\n\ts.destination = destination\n\treturn s\n}\n\n// DestinationIndex specifies the destination index of the reindexing process.\nfunc (s *ReindexService) DestinationIndex(index string) *ReindexService {\n\tif s.destination == nil {\n\t\ts.destination = NewReindexDestination()\n\t}\n\ts.destination = s.destination.Index(index)\n\treturn s\n}\n\n// DestinationIndexAndType specifies both the destination index and type\n// of the reindexing process.\nfunc (s *ReindexService) DestinationIndexAndType(index, typ string) *ReindexService {\n\tif s.destination == nil {\n\t\ts.destination = NewReindexDestination()\n\t}\n\ts.destination = s.destination.Index(index)\n\ts.destination = s.destination.Type(typ)\n\treturn s\n}\n\n// Conflicts indicates what to do when the process detects version conflicts.\n// Possible values are \"proceed\" and \"abort\".\nfunc (s *ReindexService) Conflicts(conflicts string) *ReindexService {\n\ts.conflicts = conflicts\n\treturn s\n}\n\n// AbortOnVersionConflict aborts the request on version conflicts.\n// It is an alias to setting Conflicts(\"abort\").\nfunc (s *ReindexService) AbortOnVersionConflict() *ReindexService {\n\ts.conflicts = \"abort\"\n\treturn s\n}\n\n// ProceedOnVersionConflict aborts the request on version conflicts.\n// It is an alias to setting Conflicts(\"proceed\").\nfunc (s *ReindexService) ProceedOnVersionConflict() *ReindexService {\n\ts.conflicts = \"proceed\"\n\treturn s\n}\n\n// Size sets an upper limit for the number of processed documents.\nfunc (s *ReindexService) Size(size int) *ReindexService {\n\ts.size = &size\n\treturn s\n}\n\n// Script allows for modification of the documents as they are reindexed\n// from source to destination.\nfunc (s *ReindexService) Script(script *Script) *ReindexService {\n\ts.script = script\n\treturn s\n}\n\n// Body specifies the body of the request to send to Elasticsearch.\n// It overrides settings specified with other setters, e.g. Query.\nfunc (s *ReindexService) Body(body interface{}) *ReindexService {\n\ts.body = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ReindexService) buildURL() (string, url.Values, error) {\n\t// Build URL path\n\tpath := \"/_reindex\"\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Set(\"refresh\", s.refresh)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.requestsPerSecond != nil {\n\t\tparams.Set(\"requests_per_second\", fmt.Sprintf(\"%v\", *s.requestsPerSecond))\n\t}\n\tif s.slices != nil {\n\t\tparams.Set(\"slices\", fmt.Sprintf(\"%v\", s.slices))\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\tif s.waitForCompletion != nil {\n\t\tparams.Set(\"wait_for_completion\", fmt.Sprintf(\"%v\", *s.waitForCompletion))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ReindexService) Validate() error {\n\tvar invalid []string\n\tif s.body != nil {\n\t\treturn nil\n\t}\n\tif s.source == nil {\n\t\tinvalid = append(invalid, \"Source\")\n\t} else {\n\t\tif len(s.source.request.indices) == 0 {\n\t\t\tinvalid = append(invalid, \"Source.Index\")\n\t\t}\n\t}\n\tif s.destination == nil {\n\t\tinvalid = append(invalid, \"Destination\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// getBody returns the body part of the document request.\nfunc (s *ReindexService) getBody() (interface{}, error) {\n\tif s.body != nil {\n\t\treturn s.body, nil\n\t}\n\n\tbody := make(map[string]interface{})\n\n\tif s.conflicts != \"\" {\n\t\tbody[\"conflicts\"] = s.conflicts\n\t}\n\tif s.size != nil {\n\t\tbody[\"size\"] = *s.size\n\t}\n\tif s.script != nil {\n\t\tout, err := s.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbody[\"script\"] = out\n\t}\n\n\tsrc, err := s.source.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tbody[\"source\"] = src\n\n\tdst, err := s.destination.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tbody[\"dest\"] = dst\n\n\treturn body, nil\n}\n\n// Do executes the operation.\nfunc (s *ReindexService) Do(ctx context.Context) (*BulkIndexByScrollResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tbody, err := s.getBody()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(BulkIndexByScrollResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\tret.Header = res.Header\n\treturn ret, nil\n}\n\n// DoAsync executes the reindexing operation asynchronously by starting a new task.\n// Callers need to use the Task Management API to watch the outcome of the reindexing\n// operation.\nfunc (s *ReindexService) DoAsync(ctx context.Context) (*StartTaskResult, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// DoAsync only makes sense with WaitForCompletion set to false\n\tif s.waitForCompletion != nil && *s.waitForCompletion {\n\t\treturn nil, fmt.Errorf(\"cannot start a task with WaitForCompletion set to true\")\n\t}\n\tf := false\n\ts.waitForCompletion = &f\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tbody, err := s.getBody()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(StartTaskResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\tret.Header = res.Header\n\treturn ret, nil\n}\n\n// -- Source of Reindex --\n\n// ReindexSource specifies the source of a Reindex process.\ntype ReindexSource struct {\n\trequest    *SearchRequest\n\tremoteInfo *ReindexRemoteInfo\n}\n\n// NewReindexSource creates a new ReindexSource.\nfunc NewReindexSource() *ReindexSource {\n\treturn &ReindexSource{\n\t\trequest: NewSearchRequest(),\n\t}\n}\n\n// Request specifies the search request used for source.\nfunc (r *ReindexSource) Request(request *SearchRequest) *ReindexSource {\n\tif request == nil {\n\t\tr.request = NewSearchRequest()\n\t} else {\n\t\tr.request = request\n\t}\n\treturn r\n}\n\n// SearchType is the search operation type. Possible values are\n// \"query_then_fetch\" and \"dfs_query_then_fetch\".\nfunc (r *ReindexSource) SearchType(searchType string) *ReindexSource {\n\tr.request = r.request.SearchType(searchType)\n\treturn r\n}\n\nfunc (r *ReindexSource) SearchTypeDfsQueryThenFetch() *ReindexSource {\n\tr.request = r.request.SearchType(\"dfs_query_then_fetch\")\n\treturn r\n}\n\nfunc (r *ReindexSource) SearchTypeQueryThenFetch() *ReindexSource {\n\tr.request = r.request.SearchType(\"query_then_fetch\")\n\treturn r\n}\n\nfunc (r *ReindexSource) Index(indices ...string) *ReindexSource {\n\tr.request = r.request.Index(indices...)\n\treturn r\n}\n\nfunc (r *ReindexSource) Type(types ...string) *ReindexSource {\n\tr.request = r.request.Type(types...)\n\treturn r\n}\n\nfunc (r *ReindexSource) Preference(preference string) *ReindexSource {\n\tr.request = r.request.Preference(preference)\n\treturn r\n}\n\nfunc (r *ReindexSource) RequestCache(requestCache bool) *ReindexSource {\n\tr.request = r.request.RequestCache(requestCache)\n\treturn r\n}\n\nfunc (r *ReindexSource) Scroll(scroll string) *ReindexSource {\n\tr.request = r.request.Scroll(scroll)\n\treturn r\n}\n\nfunc (r *ReindexSource) Query(query Query) *ReindexSource {\n\tr.request = r.request.Query(query)\n\treturn r\n}\n\n// Sort adds a sort order.\nfunc (r *ReindexSource) Sort(field string, ascending bool) *ReindexSource {\n\tr.request = r.request.Sort(field, ascending)\n\treturn r\n}\n\n// SortWithInfo adds a sort order.\nfunc (r *ReindexSource) SortWithInfo(info SortInfo) *ReindexSource {\n\tr.request = r.request.SortWithInfo(info)\n\treturn r\n}\n\n// SortBy adds a sort order.\nfunc (r *ReindexSource) SortBy(sorter ...Sorter) *ReindexSource {\n\tr.request = r.request.SortBy(sorter...)\n\treturn r\n}\n\n// FetchSource indicates whether the response should contain the stored\n// _source for every hit.\nfunc (r *ReindexSource) FetchSource(fetchSource bool) *ReindexSource {\n\tr.request = r.request.FetchSource(fetchSource)\n\treturn r\n}\n\n// FetchSourceIncludeExclude specifies that _source should be returned\n// with each hit, where \"include\" and \"exclude\" serve as a simple wildcard\n// matcher that gets applied to its fields\n// (e.g. include := []string{\"obj1.*\",\"obj2.*\"}, exclude := []string{\"description.*\"}).\nfunc (r *ReindexSource) FetchSourceIncludeExclude(include, exclude []string) *ReindexSource {\n\tr.request = r.request.FetchSourceIncludeExclude(include, exclude)\n\treturn r\n}\n\n// FetchSourceContext indicates how the _source should be fetched.\nfunc (r *ReindexSource) FetchSourceContext(fsc *FetchSourceContext) *ReindexSource {\n\tr.request = r.request.FetchSourceContext(fsc)\n\treturn r\n}\n\n// RemoteInfo sets up reindexing from a remote cluster.\nfunc (r *ReindexSource) RemoteInfo(ri *ReindexRemoteInfo) *ReindexSource {\n\tr.remoteInfo = ri\n\treturn r\n}\n\n// Source returns a serializable JSON request for the request.\nfunc (r *ReindexSource) Source() (interface{}, error) {\n\tsrc, err := r.request.sourceAsMap()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsource, ok := src.(map[string]interface{})\n\tif !ok {\n\t\treturn nil, errors.New(\"unable to use SearchRequest as map[string]interface{}\")\n\t}\n\n\tswitch len(r.request.indices) {\n\tcase 1:\n\t\tsource[\"index\"] = r.request.indices[0]\n\tdefault:\n\t\tsource[\"index\"] = r.request.indices\n\t}\n\tswitch len(r.request.types) {\n\tcase 0:\n\tcase 1:\n\t\tsource[\"type\"] = r.request.types[0]\n\tdefault:\n\t\tsource[\"type\"] = r.request.types\n\t}\n\tif r.remoteInfo != nil {\n\t\tsrc, err := r.remoteInfo.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"remote\"] = src\n\t}\n\treturn source, nil\n}\n\n// ReindexRemoteInfo contains information for reindexing from a remote cluster.\ntype ReindexRemoteInfo struct {\n\thost           string\n\tusername       string\n\tpassword       string\n\tsocketTimeout  string // e.g. \"1m\" or \"30s\"\n\tconnectTimeout string // e.g. \"1m\" or \"30s\"\n}\n\n// NewReindexRemoteInfo creates a new ReindexRemoteInfo.\nfunc NewReindexRemoteInfo() *ReindexRemoteInfo {\n\treturn &ReindexRemoteInfo{}\n}\n\n// Host sets the host information of the remote cluster.\n// It must be of the form \"http(s)://<hostname>:<port>\"\nfunc (ri *ReindexRemoteInfo) Host(host string) *ReindexRemoteInfo {\n\tri.host = host\n\treturn ri\n}\n\n// Username sets the username to authenticate with the remote cluster.\nfunc (ri *ReindexRemoteInfo) Username(username string) *ReindexRemoteInfo {\n\tri.username = username\n\treturn ri\n}\n\n// Password sets the password to authenticate with the remote cluster.\nfunc (ri *ReindexRemoteInfo) Password(password string) *ReindexRemoteInfo {\n\tri.password = password\n\treturn ri\n}\n\n// SocketTimeout sets the socket timeout to connect with the remote cluster.\n// Use ES compatible values like e.g. \"30s\" or \"1m\".\nfunc (ri *ReindexRemoteInfo) SocketTimeout(timeout string) *ReindexRemoteInfo {\n\tri.socketTimeout = timeout\n\treturn ri\n}\n\n// ConnectTimeout sets the connection timeout to connect with the remote cluster.\n// Use ES compatible values like e.g. \"30s\" or \"1m\".\nfunc (ri *ReindexRemoteInfo) ConnectTimeout(timeout string) *ReindexRemoteInfo {\n\tri.connectTimeout = timeout\n\treturn ri\n}\n\n// Source returns the serializable JSON data for the request.\nfunc (ri *ReindexRemoteInfo) Source() (interface{}, error) {\n\tres := make(map[string]interface{})\n\tres[\"host\"] = ri.host\n\tif len(ri.username) > 0 {\n\t\tres[\"username\"] = ri.username\n\t}\n\tif len(ri.password) > 0 {\n\t\tres[\"password\"] = ri.password\n\t}\n\tif len(ri.socketTimeout) > 0 {\n\t\tres[\"socket_timeout\"] = ri.socketTimeout\n\t}\n\tif len(ri.connectTimeout) > 0 {\n\t\tres[\"connect_timeout\"] = ri.connectTimeout\n\t}\n\treturn res, nil\n}\n\n// -- Destination of Reindex --\n\n// ReindexDestination is the destination of a Reindex API call.\n// It is basically the meta data of a BulkIndexRequest.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-reindex.html\n// for details.\ntype ReindexDestination struct {\n\tindex       string\n\ttyp         string\n\trouting     string\n\tparent      string\n\topType      string\n\tversion     int64  // default is MATCH_ANY\n\tversionType string // default is \"internal\"\n\tpipeline    string\n}\n\n// NewReindexDestination returns a new ReindexDestination.\nfunc NewReindexDestination() *ReindexDestination {\n\treturn &ReindexDestination{}\n}\n\n// Index specifies name of the Elasticsearch index to use as the destination\n// of a reindexing process.\nfunc (r *ReindexDestination) Index(index string) *ReindexDestination {\n\tr.index = index\n\treturn r\n}\n\n// Type specifies the Elasticsearch type to use for reindexing.\nfunc (r *ReindexDestination) Type(typ string) *ReindexDestination {\n\tr.typ = typ\n\treturn r\n}\n\n// Routing specifies a routing value for the reindexing request.\n// It can be \"keep\", \"discard\", or start with \"=\". The latter specifies\n// the routing on the bulk request.\nfunc (r *ReindexDestination) Routing(routing string) *ReindexDestination {\n\tr.routing = routing\n\treturn r\n}\n\n// Keep sets the routing on the bulk request sent for each match to the routing\n// of the match (the default).\nfunc (r *ReindexDestination) Keep() *ReindexDestination {\n\tr.routing = \"keep\"\n\treturn r\n}\n\n// Discard sets the routing on the bulk request sent for each match to null.\nfunc (r *ReindexDestination) Discard() *ReindexDestination {\n\tr.routing = \"discard\"\n\treturn r\n}\n\n// Parent specifies the identifier of the parent document (if available).\nfunc (r *ReindexDestination) Parent(parent string) *ReindexDestination {\n\tr.parent = parent\n\treturn r\n}\n\n// OpType specifies if this request should follow create-only or upsert\n// behavior. This follows the OpType of the standard document index API.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-index_.html#operation-type\n// for details.\nfunc (r *ReindexDestination) OpType(opType string) *ReindexDestination {\n\tr.opType = opType\n\treturn r\n}\n\n// Version indicates the version of the document as part of an optimistic\n// concurrency model.\nfunc (r *ReindexDestination) Version(version int64) *ReindexDestination {\n\tr.version = version\n\treturn r\n}\n\n// VersionType specifies how versions are created.\nfunc (r *ReindexDestination) VersionType(versionType string) *ReindexDestination {\n\tr.versionType = versionType\n\treturn r\n}\n\n// Pipeline specifies the pipeline to use for reindexing.\nfunc (r *ReindexDestination) Pipeline(pipeline string) *ReindexDestination {\n\tr.pipeline = pipeline\n\treturn r\n}\n\n// Source returns a serializable JSON request for the request.\nfunc (r *ReindexDestination) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif r.index != \"\" {\n\t\tsource[\"index\"] = r.index\n\t}\n\tif r.typ != \"\" {\n\t\tsource[\"type\"] = r.typ\n\t}\n\tif r.routing != \"\" {\n\t\tsource[\"routing\"] = r.routing\n\t}\n\tif r.opType != \"\" {\n\t\tsource[\"op_type\"] = r.opType\n\t}\n\tif r.parent != \"\" {\n\t\tsource[\"parent\"] = r.parent\n\t}\n\tif r.version > 0 {\n\t\tsource[\"version\"] = r.version\n\t}\n\tif r.versionType != \"\" {\n\t\tsource[\"version_type\"] = r.versionType\n\t}\n\tif r.pipeline != \"\" {\n\t\tsource[\"pipeline\"] = r.pipeline\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "reindex_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestReindexSourceWithBodyMap(t *testing.T) {\n\tclient := setupTestClient(t)\n\tout, err := client.Reindex().Body(map[string]interface{}{\n\t\t\"source\": map[string]interface{}{\n\t\t\t\"index\": \"twitter\",\n\t\t},\n\t\t\"dest\": map[string]interface{}{\n\t\t\t\"index\": \"new_twitter\",\n\t\t},\n\t}).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"new_twitter\"},\"source\":{\"index\":\"twitter\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithBodyString(t *testing.T) {\n\tclient := setupTestClient(t)\n\tgot, err := client.Reindex().Body(`{\"source\":{\"index\":\"twitter\"},\"dest\":{\"index\":\"new_twitter\"}}`).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant := `{\"source\":{\"index\":\"twitter\"},\"dest\":{\"index\":\"new_twitter\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithSourceIndexAndDestinationIndex(t *testing.T) {\n\tclient := setupTestClient(t)\n\tout, err := client.Reindex().SourceIndex(\"twitter\").DestinationIndex(\"new_twitter\").getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"new_twitter\"},\"source\":{\"index\":\"twitter\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithSourceAndDestinationAndVersionType(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\")\n\tdst := NewReindexDestination().Index(\"new_twitter\").VersionType(\"external\")\n\tout, err := client.Reindex().Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"new_twitter\",\"version_type\":\"external\"},\"source\":{\"index\":\"twitter\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithSourceAndRemoteAndDestination(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\").RemoteInfo(\n\t\tNewReindexRemoteInfo().Host(\"http://otherhost:9200\").\n\t\t\tUsername(\"alice\").\n\t\t\tPassword(\"secret\").\n\t\t\tConnectTimeout(\"10s\").\n\t\t\tSocketTimeout(\"1m\"),\n\t)\n\tdst := NewReindexDestination().Index(\"new_twitter\")\n\tout, err := client.Reindex().Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"new_twitter\"},\"source\":{\"index\":\"twitter\",\"remote\":{\"connect_timeout\":\"10s\",\"host\":\"http://otherhost:9200\",\"password\":\"secret\",\"socket_timeout\":\"1m\",\"username\":\"alice\"}}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithSourceAndDestinationAndOpTypeAndPipeline(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\")\n\tdst := NewReindexDestination().Index(\"new_twitter\").OpType(\"create\").Pipeline(\"some_ingest_pipeline\")\n\tout, err := client.Reindex().Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"new_twitter\",\"op_type\":\"create\",\"pipeline\":\"some_ingest_pipeline\"},\"source\":{\"index\":\"twitter\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithConflictsProceed(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\")\n\tdst := NewReindexDestination().Index(\"new_twitter\").OpType(\"create\")\n\tout, err := client.Reindex().Conflicts(\"proceed\").Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"conflicts\":\"proceed\",\"dest\":{\"index\":\"new_twitter\",\"op_type\":\"create\"},\"source\":{\"index\":\"twitter\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithProceedOnVersionConflict(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\")\n\tdst := NewReindexDestination().Index(\"new_twitter\").OpType(\"create\")\n\tout, err := client.Reindex().ProceedOnVersionConflict().Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"conflicts\":\"proceed\",\"dest\":{\"index\":\"new_twitter\",\"op_type\":\"create\"},\"source\":{\"index\":\"twitter\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithQuery(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\").Query(NewTermQuery(\"user\", \"olivere\"))\n\tdst := NewReindexDestination().Index(\"new_twitter\")\n\tout, err := client.Reindex().Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"new_twitter\"},\"source\":{\"index\":\"twitter\",\"query\":{\"term\":{\"user\":\"olivere\"}}}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithMultipleSourceIndicesAndTypes(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\", \"blog\").Type(\"doc\", \"post\")\n\tdst := NewReindexDestination().Index(\"all_together\")\n\tout, err := client.Reindex().Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"all_together\"},\"source\":{\"index\":[\"twitter\",\"blog\"],\"type\":[\"doc\",\"post\"]}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithSourceAndSize(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\").Sort(\"date\", false)\n\tdst := NewReindexDestination().Index(\"new_twitter\")\n\tout, err := client.Reindex().Size(10000).Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"new_twitter\"},\"size\":10000,\"source\":{\"index\":\"twitter\",\"sort\":[{\"date\":{\"order\":\"desc\"}}]}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithScript(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\")\n\tdst := NewReindexDestination().Index(\"new_twitter\").VersionType(\"external\")\n\tscr := NewScriptInline(\"if (ctx._source.foo == 'bar') {ctx._version++; ctx._source.remove('foo')}\")\n\tout, err := client.Reindex().Source(src).Destination(dst).Script(scr).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"new_twitter\",\"version_type\":\"external\"},\"script\":{\"source\":\"if (ctx._source.foo == 'bar') {ctx._version++; ctx._source.remove('foo')}\"},\"source\":{\"index\":\"twitter\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithRouting(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"source\").Query(NewMatchQuery(\"company\", \"cat\"))\n\tdst := NewReindexDestination().Index(\"dest\").Routing(\"=cat\")\n\tout, err := client.Reindex().Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"dest\",\"routing\":\"=cat\"},\"source\":{\"index\":\"source\",\"query\":{\"match\":{\"company\":{\"query\":\"cat\"}}}}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindexSourceWithSourceFilter(t *testing.T) {\n\tclient := setupTestClient(t)\n\tsrc := NewReindexSource().Index(\"twitter\").\n\t\tFetchSourceIncludeExclude([]string{\"obj1.*\", \"obj2.*\"}, []string{\"*.description\"})\n\tdst := NewReindexDestination().Index(\"new_twitter\")\n\tout, err := client.Reindex().Source(src).Destination(dst).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"dest\":{\"index\":\"new_twitter\"},\"source\":{\"_source\":{\"excludes\":[\"*.description\"],\"includes\":[\"obj1.*\",\"obj2.*\"]},\"index\":\"twitter\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestReindex(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tsourceCount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif sourceCount <= 0 {\n\t\tt.Fatalf(\"expected more than %d documents; got: %d\", 0, sourceCount)\n\t}\n\n\ttargetCount, err := client.Count(testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif targetCount != 0 {\n\t\tt.Fatalf(\"expected %d documents; got: %d\", 0, targetCount)\n\t}\n\n\t// Simple copying\n\tsrc := NewReindexSource().Index(testIndexName)\n\tdst := NewReindexDestination().Index(testIndexName2)\n\tres, err := client.Reindex().\n\t\tSource(src).\n\t\tDestination(dst).\n\t\tRefresh(\"true\").\n\t\tHeader(\"X-Opaque-Id\", \"987654\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected result != nil\")\n\t}\n\tif res.Total != sourceCount {\n\t\tt.Errorf(\"expected %d, got %d\", sourceCount, res.Total)\n\t}\n\tif res.Updated != 0 {\n\t\tt.Errorf(\"expected %d, got %d\", 0, res.Updated)\n\t}\n\tif res.Created != sourceCount {\n\t\tt.Errorf(\"expected %d, got %d\", sourceCount, res.Created)\n\t}\n\tif want, have := \"987654\", res.Header.Get(\"X-Opaque-Id\"); want != have {\n\t\tt.Fatalf(\"expected HTTP header %#v; got: %#v\", want, have)\n\t}\n\n\ttargetCount, err = client.Count(testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif targetCount != sourceCount {\n\t\tt.Fatalf(\"expected %d documents; got: %d\", sourceCount, targetCount)\n\t}\n}\n\nfunc TestReindexAsync(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tsourceCount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif sourceCount <= 0 {\n\t\tt.Fatalf(\"expected more than %d documents; got: %d\", 0, sourceCount)\n\t}\n\n\ttargetCount, err := client.Count(testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif targetCount != 0 {\n\t\tt.Fatalf(\"expected %d documents; got: %d\", 0, targetCount)\n\t}\n\n\t// Simple copying\n\tsrc := NewReindexSource().Index(testIndexName)\n\tdst := NewReindexDestination().Index(testIndexName2)\n\tres, err := client.Reindex().\n\t\tSource(src).\n\t\tDestination(dst).\n\t\tSlices(\"auto\").\n\t\tHeader(\"X-Opaque-Id\", \"987654\").\n\t\tDoAsync(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected result != nil\")\n\t}\n\tif res.TaskId == \"\" {\n\t\tt.Errorf(\"expected a task id, got %+v\", res)\n\t}\n\tif want, have := \"987654\", res.Header.Get(\"X-Opaque-Id\"); want != have {\n\t\tt.Fatalf(\"expected HTTP header %#v; got: %#v\", want, have)\n\t}\n\n\ttasksGetTask := client.TasksGetTask()\n\ttaskStatus, err := tasksGetTask.TaskId(res.TaskId).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif taskStatus == nil {\n\t\tt.Fatal(\"expected task status result != nil\")\n\t}\n}\n\nfunc TestReindexWithWaitForCompletionTrueCannotBeStarted(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\tesversion, err := client.ElasticsearchVersion(DefaultURL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif esversion < \"2.3.0\" {\n\t\tt.Skipf(\"Elasticsearch %v does not support Reindex API yet\", esversion)\n\t}\n\n\tsourceCount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif sourceCount <= 0 {\n\t\tt.Fatalf(\"expected more than %d documents; got: %d\", 0, sourceCount)\n\t}\n\n\ttargetCount, err := client.Count(testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif targetCount != 0 {\n\t\tt.Fatalf(\"expected %d documents; got: %d\", 0, targetCount)\n\t}\n\n\t// DoAsync should fail when WaitForCompletion is true\n\tsrc := NewReindexSource().Index(testIndexName)\n\tdst := NewReindexDestination().Index(testIndexName2)\n\t_, err = client.Reindex().Source(src).Destination(dst).WaitForCompletion(true).DoAsync(context.TODO())\n\tif err == nil {\n\t\tt.Fatal(\"error should have been returned\")\n\t}\n}\n"
  },
  {
    "path": "request.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"strings\"\n)\n\n// Elasticsearch-specific HTTP request\ntype Request http.Request\n\n// NewRequest is a http.Request and adds features such as encoding the body.\nfunc NewRequest(method, url string) (*Request, error) {\n\treq, err := http.NewRequest(method, url, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treq.Header.Add(\"Accept\", \"application/json\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treturn (*Request)(req), nil\n}\n\n// SetBasicAuth wraps http.Request's SetBasicAuth.\nfunc (r *Request) SetBasicAuth(username, password string) {\n\t((*http.Request)(r)).SetBasicAuth(username, password)\n}\n\n// SetBody encodes the body in the request. You may pass a flag to\n// compress the request via gzip.\nfunc (r *Request) SetBody(body interface{}, gzipCompress bool) error {\n\tswitch b := body.(type) {\n\tcase string:\n\t\tif gzipCompress {\n\t\t\treturn r.setBodyGzip(b)\n\t\t}\n\t\treturn r.setBodyString(b)\n\tdefault:\n\t\tif gzipCompress {\n\t\t\treturn r.setBodyGzip(body)\n\t\t}\n\t\treturn r.setBodyJson(body)\n\t}\n}\n\n// setBodyJson encodes the body as a struct to be marshaled via json.Marshal.\nfunc (r *Request) setBodyJson(data interface{}) error {\n\tbody, err := json.Marshal(data)\n\tif err != nil {\n\t\treturn err\n\t}\n\tr.Header.Set(\"Content-Type\", \"application/json\")\n\tr.setBodyReader(bytes.NewReader(body))\n\treturn nil\n}\n\n// setBodyString encodes the body as a string.\nfunc (r *Request) setBodyString(body string) error {\n\treturn r.setBodyReader(strings.NewReader(body))\n}\n\n// setBodyGzip gzip's the body. It accepts both strings and structs as body.\n// The latter will be encoded via json.Marshal.\nfunc (r *Request) setBodyGzip(body interface{}) error {\n\tswitch b := body.(type) {\n\tcase string:\n\t\tbuf := new(bytes.Buffer)\n\t\tw := gzip.NewWriter(buf)\n\t\tif _, err := w.Write([]byte(b)); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := w.Close(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tr.Header.Add(\"Content-Encoding\", \"gzip\")\n\t\tr.Header.Add(\"Vary\", \"Accept-Encoding\")\n\t\treturn r.setBodyReader(bytes.NewReader(buf.Bytes()))\n\tdefault:\n\t\tdata, err := json.Marshal(b)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tbuf := new(bytes.Buffer)\n\t\tw := gzip.NewWriter(buf)\n\t\tif _, err := w.Write(data); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := w.Close(); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tr.Header.Add(\"Content-Encoding\", \"gzip\")\n\t\tr.Header.Add(\"Vary\", \"Accept-Encoding\")\n\t\tr.Header.Set(\"Content-Type\", \"application/json\")\n\t\treturn r.setBodyReader(bytes.NewReader(buf.Bytes()))\n\t}\n}\n\n// setBodyReader writes the body from an io.Reader.\nfunc (r *Request) setBodyReader(body io.Reader) error {\n\trc, ok := body.(io.ReadCloser)\n\tif !ok && body != nil {\n\t\trc = ioutil.NopCloser(body)\n\t}\n\tr.Body = rc\n\tif body != nil {\n\t\tswitch v := body.(type) {\n\t\tcase *strings.Reader:\n\t\t\tr.ContentLength = int64(v.Len())\n\t\tcase *bytes.Buffer:\n\t\t\tr.ContentLength = int64(v.Len())\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "request_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nvar testReq *Request // used as a temporary variable to avoid compiler optimizations in tests/benchmarks\n\nfunc TestRequestSetContentType(t *testing.T) {\n\treq, err := NewRequest(\"GET\", \"/\")\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := \"application/json\", req.Header.Get(\"Content-Type\"); want != have {\n\t\tt.Fatalf(\"want Content-Type=%q, have %q\", want, have)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/x-ndjson\")\n\tif want, have := \"application/x-ndjson\", req.Header.Get(\"Content-Type\"); want != have {\n\t\tt.Fatalf(\"want Content-Type=%q, have %q\", want, have)\n\t}\n\tif want, have := \"\", req.Header.Get(\"User-Agent\"); want != have {\n\t\tt.Fatalf(\"want User-Agent=%q, have %q\", want, have)\n\t}\n}\n\nfunc BenchmarkRequestSetBodyString(b *testing.B) {\n\treq, err := NewRequest(\"GET\", \"/\")\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\tfor i := 0; i < b.N; i++ {\n\t\tbody := `{\"query\":{\"match_all\":{}}}`\n\t\terr = req.SetBody(body, false)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n\ttestReq = req\n\tb.ReportAllocs()\n}\n\nfunc BenchmarkRequestSetBodyStringGzip(b *testing.B) {\n\treq, err := NewRequest(\"GET\", \"/\")\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\tfor i := 0; i < b.N; i++ {\n\t\tbody := `{\"query\":{\"match_all\":{}}}`\n\t\terr = req.SetBody(body, true)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n\ttestReq = req\n\tb.ReportAllocs()\n}\n\nfunc BenchmarkRequestSetBodyBytes(b *testing.B) {\n\treq, err := NewRequest(\"GET\", \"/\")\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\tfor i := 0; i < b.N; i++ {\n\t\tbody := []byte(`{\"query\":{\"match_all\":{}}}`)\n\t\terr = req.SetBody(body, false)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n\ttestReq = req\n\tb.ReportAllocs()\n}\n\nfunc BenchmarkRequestSetBodyBytesGzip(b *testing.B) {\n\treq, err := NewRequest(\"GET\", \"/\")\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\tfor i := 0; i < b.N; i++ {\n\t\tbody := []byte(`{\"query\":{\"match_all\":{}}}`)\n\t\terr = req.SetBody(body, true)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n\ttestReq = req\n\tb.ReportAllocs()\n}\n\nfunc BenchmarkRequestSetBodyMap(b *testing.B) {\n\treq, err := NewRequest(\"GET\", \"/\")\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\tfor i := 0; i < b.N; i++ {\n\t\tbody := map[string]interface{}{\n\t\t\t\"query\": map[string]interface{}{\n\t\t\t\t\"match_all\": map[string]interface{}{},\n\t\t\t},\n\t\t}\n\t\terr = req.SetBody(body, false)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n\ttestReq = req\n\tb.ReportAllocs()\n}\n\nfunc BenchmarkRequestSetBodyMapGzip(b *testing.B) {\n\treq, err := NewRequest(\"GET\", \"/\")\n\tif err != nil {\n\t\tb.Fatal(err)\n\t}\n\tfor i := 0; i < b.N; i++ {\n\t\tbody := map[string]interface{}{\n\t\t\t\"query\": map[string]interface{}{\n\t\t\t\t\"match_all\": map[string]interface{}{},\n\t\t\t},\n\t\t}\n\t\terr = req.SetBody(body, true)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t}\n\ttestReq = req\n\tb.ReportAllocs()\n}\n"
  },
  {
    "path": "rescore.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\ntype Rescore struct {\n\trescorer                 Rescorer\n\twindowSize               *int\n\tdefaultRescoreWindowSize *int\n}\n\nfunc NewRescore() *Rescore {\n\treturn &Rescore{}\n}\n\nfunc (r *Rescore) WindowSize(windowSize int) *Rescore {\n\tr.windowSize = &windowSize\n\treturn r\n}\n\nfunc (r *Rescore) IsEmpty() bool {\n\treturn r.rescorer == nil\n}\n\nfunc (r *Rescore) Rescorer(rescorer Rescorer) *Rescore {\n\tr.rescorer = rescorer\n\treturn r\n}\n\nfunc (r *Rescore) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif r.windowSize != nil {\n\t\tsource[\"window_size\"] = *r.windowSize\n\t} else if r.defaultRescoreWindowSize != nil {\n\t\tsource[\"window_size\"] = *r.defaultRescoreWindowSize\n\t}\n\trescorerSrc, err := r.rescorer.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsource[r.rescorer.Name()] = rescorerSrc\n\treturn source, nil\n}\n"
  },
  {
    "path": "rescorer.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\ntype Rescorer interface {\n\tName() string\n\tSource() (interface{}, error)\n}\n\n// -- Query Rescorer --\n\ntype QueryRescorer struct {\n\tquery              Query\n\trescoreQueryWeight *float64\n\tqueryWeight        *float64\n\tscoreMode          string\n}\n\nfunc NewQueryRescorer(query Query) *QueryRescorer {\n\treturn &QueryRescorer{\n\t\tquery: query,\n\t}\n}\n\nfunc (r *QueryRescorer) Name() string {\n\treturn \"query\"\n}\n\nfunc (r *QueryRescorer) RescoreQueryWeight(rescoreQueryWeight float64) *QueryRescorer {\n\tr.rescoreQueryWeight = &rescoreQueryWeight\n\treturn r\n}\n\nfunc (r *QueryRescorer) QueryWeight(queryWeight float64) *QueryRescorer {\n\tr.queryWeight = &queryWeight\n\treturn r\n}\n\nfunc (r *QueryRescorer) ScoreMode(scoreMode string) *QueryRescorer {\n\tr.scoreMode = scoreMode\n\treturn r\n}\n\nfunc (r *QueryRescorer) Source() (interface{}, error) {\n\trescoreQuery, err := r.query.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tsource := make(map[string]interface{})\n\tsource[\"rescore_query\"] = rescoreQuery\n\tif r.queryWeight != nil {\n\t\tsource[\"query_weight\"] = *r.queryWeight\n\t}\n\tif r.rescoreQueryWeight != nil {\n\t\tsource[\"rescore_query_weight\"] = *r.rescoreQueryWeight\n\t}\n\tif r.scoreMode != \"\" {\n\t\tsource[\"score_mode\"] = r.scoreMode\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "response.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"net/http\"\n)\n\nvar (\n\t// ErrResponseSize is raised if a response body exceeds the given max body size.\n\tErrResponseSize = errors.New(\"elastic: response size too large\")\n)\n\n// Response represents a response from Elasticsearch.\ntype Response struct {\n\t// StatusCode is the HTTP status code, e.g. 200.\n\tStatusCode int\n\t// Header is the HTTP header from the HTTP response.\n\t// Keys in the map are canonicalized (see http.CanonicalHeaderKey).\n\tHeader http.Header\n\t// Body is the deserialized response body. Only available if streaming is disabled.\n\tBody json.RawMessage\n\t// DeprecationWarnings lists all deprecation warnings returned from\n\t// Elasticsearch.\n\tDeprecationWarnings []string\n\t// BodyReader is the body as a reader. Only available if streaming is enabled.\n\tBodyReader io.ReadCloser\n}\n\n// newResponse creates a new response from the HTTP response.\nfunc (c *Client) newResponse(res *http.Response, maxBodySize int64, stream bool) (*Response, error) {\n\tr := &Response{\n\t\tStatusCode:          res.StatusCode,\n\t\tHeader:              res.Header,\n\t\tDeprecationWarnings: res.Header[\"Warning\"],\n\t}\n\tif stream {\n\t\tr.BodyReader = res.Body\n\t} else if res.Body != nil {\n\t\tbody := io.Reader(res.Body)\n\t\tif maxBodySize > 0 {\n\t\t\tif res.ContentLength > maxBodySize {\n\t\t\t\treturn nil, ErrResponseSize\n\t\t\t}\n\t\t\tbody = io.LimitReader(body, maxBodySize+1)\n\t\t}\n\t\tslurp, err := ioutil.ReadAll(body)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif maxBodySize > 0 && int64(len(slurp)) > maxBodySize {\n\t\t\treturn nil, ErrResponseSize\n\t\t}\n\t\t// HEAD requests return a body but no content\n\t\tif len(slurp) > 0 {\n\t\t\tr.Body = json.RawMessage(slurp)\n\t\t}\n\t}\n\treturn r, nil\n}\n"
  },
  {
    "path": "response_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"testing\"\n)\n\nfunc BenchmarkResponse(b *testing.B) {\n\tc := &Client{\n\t\tdecoder: &DefaultDecoder{},\n\t}\n\n\tvar resp *Response\n\tfor n := 0; n < b.N; n++ {\n\t\titeration := fmt.Sprint(n)\n\t\tbody := fmt.Sprintf(`{\"n\":%d}`, n)\n\t\tres := &http.Response{\n\t\t\tHeader: http.Header{\n\t\t\t\t\"X-Iteration\": []string{iteration},\n\t\t\t},\n\t\t\tBody:       ioutil.NopCloser(bytes.NewBufferString(body)),\n\t\t\tStatusCode: http.StatusOK,\n\t\t}\n\t\tvar err error\n\t\tresp, err = c.newResponse(res, 0, false)\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t\t/*\n\t\t\tif want, have := body, string(resp.Body); want != have {\n\t\t\t\tb.Fatalf(\"want %q, have %q\", want, have)\n\t\t\t}\n\t\t\t//*/\n\t\t/*\n\t\t\tif want, have := iteration, resp.Header.Get(\"X-Iteration\"); want != have {\n\t\t\t\tb.Fatalf(\"want %q, have %q\", want, have)\n\t\t\t}\n\t\t\t//*/\n\t}\n\t_ = resp\n}\n"
  },
  {
    "path": "retrier.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"time\"\n)\n\n// RetrierFunc specifies the signature of a Retry function, and is an adapter\n// to allow the use of ordinary Retry functions. If f is a function with the\n// appropriate signature, RetrierFunc(f) is a Retrier that calls f.\ntype RetrierFunc func(context.Context, int, *http.Request, *http.Response, error) (time.Duration, bool, error)\n\n// Retry calls f.\nfunc (f RetrierFunc) Retry(ctx context.Context, retry int, req *http.Request, resp *http.Response, err error) (time.Duration, bool, error) {\n\treturn f(ctx, retry, req, resp, err)\n}\n\n// Retrier decides whether to retry a failed HTTP request with Elasticsearch.\ntype Retrier interface {\n\t// Retry is called when a request has failed. It decides whether to retry\n\t// the call, how long to wait for the next call, or whether to return an\n\t// error (which will be returned to the service that started the HTTP\n\t// request in the first place).\n\t//\n\t// Callers may also use this to inspect the HTTP request/response and\n\t// the error that happened. Additional data can be passed through via\n\t// the context.\n\tRetry(ctx context.Context, retry int, req *http.Request, resp *http.Response, err error) (time.Duration, bool, error)\n}\n\n// -- StopRetrier --\n\n// StopRetrier is an implementation that does no retries.\ntype StopRetrier struct {\n}\n\n// NewStopRetrier returns a retrier that does no retries.\nfunc NewStopRetrier() *StopRetrier {\n\treturn &StopRetrier{}\n}\n\n// Retry does not retry.\nfunc (r *StopRetrier) Retry(ctx context.Context, retry int, req *http.Request, resp *http.Response, err error) (time.Duration, bool, error) {\n\treturn 0, false, nil\n}\n\n// -- BackoffRetrier --\n\n// BackoffRetrier is an implementation that does nothing but return nil on Retry.\ntype BackoffRetrier struct {\n\tbackoff Backoff\n}\n\n// NewBackoffRetrier returns a retrier that uses the given backoff strategy.\nfunc NewBackoffRetrier(backoff Backoff) *BackoffRetrier {\n\treturn &BackoffRetrier{backoff: backoff}\n}\n\n// Retry calls into the backoff strategy and its wait interval.\nfunc (r *BackoffRetrier) Retry(ctx context.Context, retry int, req *http.Request, resp *http.Response, err error) (time.Duration, bool, error) {\n\twait, goahead := r.backoff.Next(retry)\n\treturn wait, goahead, nil\n}\n"
  },
  {
    "path": "retrier_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"net/http\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n)\n\ntype testRetrier struct {\n\tRetrier\n\tN   int64\n\tErr error\n}\n\nfunc (r *testRetrier) Retry(ctx context.Context, retry int, req *http.Request, resp *http.Response, err error) (time.Duration, bool, error) {\n\tatomic.AddInt64(&r.N, 1)\n\tif r.Err != nil {\n\t\treturn 0, false, r.Err\n\t}\n\treturn r.Retrier.Retry(ctx, retry, req, resp, err)\n}\n\nfunc TestStopRetrier(t *testing.T) {\n\tr := NewStopRetrier()\n\twait, ok, err := r.Retry(context.TODO(), 1, nil, nil, nil)\n\tif want, got := 0*time.Second, wait; want != got {\n\t\tt.Fatalf(\"expected %v, got %v\", want, got)\n\t}\n\tif want, got := false, ok; want != got {\n\t\tt.Fatalf(\"expected %v, got %v\", want, got)\n\t}\n\tif err != nil {\n\t\tt.Fatalf(\"expected nil, got %v\", err)\n\t}\n}\n\nfunc TestRetrier(t *testing.T) {\n\tvar numFailedReqs int\n\tfail := func(r *http.Request) (*http.Response, error) {\n\t\tnumFailedReqs += 1\n\t\t//return &http.Response{Request: r, StatusCode: 400}, nil\n\t\treturn nil, errors.New(\"request failed\")\n\t}\n\n\ttr := &failingTransport{path: \"/fail\", fail: fail}\n\thttpClient := &http.Client{Transport: tr}\n\n\tretrier := &testRetrier{\n\t\tRetrier: NewBackoffRetrier(NewSimpleBackoff(100, 100, 100, 100, 100)),\n\t}\n\n\tclient, err := NewClient(\n\t\tSetHttpClient(httpClient),\n\t\tSetMaxRetries(5),\n\t\tSetHealthcheck(false),\n\t\tSetRetrier(retrier))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/fail\",\n\t})\n\tif err == nil {\n\t\tt.Fatal(\"expected error\")\n\t}\n\tif res != nil {\n\t\tt.Fatal(\"expected no response\")\n\t}\n\t// Connection should be marked as dead after it failed\n\tif numFailedReqs != 5 {\n\t\tt.Errorf(\"expected %d failed requests; got: %d\", 5, numFailedReqs)\n\t}\n\tif retrier.N != 5 {\n\t\tt.Errorf(\"expected %d Retrier calls; got: %d\", 5, retrier.N)\n\t}\n}\n\nfunc TestRetrierWithError(t *testing.T) {\n\tvar numFailedReqs int\n\tfail := func(r *http.Request) (*http.Response, error) {\n\t\tnumFailedReqs += 1\n\t\t//return &http.Response{Request: r, StatusCode: 400}, nil\n\t\treturn nil, errors.New(\"request failed\")\n\t}\n\n\ttr := &failingTransport{path: \"/fail\", fail: fail}\n\thttpClient := &http.Client{Transport: tr}\n\n\tkaboom := errors.New(\"kaboom\")\n\tretrier := &testRetrier{\n\t\tErr:     kaboom,\n\t\tRetrier: NewBackoffRetrier(NewSimpleBackoff(100, 100, 100, 100, 100)),\n\t}\n\n\tclient, err := NewClient(\n\t\tSetHttpClient(httpClient),\n\t\tSetMaxRetries(5),\n\t\tSetHealthcheck(false),\n\t\tSetRetrier(retrier))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod: \"GET\",\n\t\tPath:   \"/fail\",\n\t})\n\tif err != kaboom {\n\t\tt.Fatalf(\"expected %v, got %v\", kaboom, err)\n\t}\n\tif res != nil {\n\t\tt.Fatal(\"expected no response\")\n\t}\n\tif numFailedReqs != 1 {\n\t\tt.Errorf(\"expected %d failed requests; got: %d\", 1, numFailedReqs)\n\t}\n\tif retrier.N != 1 {\n\t\tt.Errorf(\"expected %d Retrier calls; got: %d\", 1, retrier.N)\n\t}\n}\n\nfunc TestRetrierOnPerformRequest(t *testing.T) {\n\tvar numFailedReqs int\n\tfail := func(r *http.Request) (*http.Response, error) {\n\t\tnumFailedReqs += 1\n\t\t//return &http.Response{Request: r, StatusCode: 400}, nil\n\t\treturn nil, errors.New(\"request failed\")\n\t}\n\n\ttr := &failingTransport{path: \"/fail\", fail: fail}\n\thttpClient := &http.Client{Transport: tr}\n\n\tdefaultRetrier := &testRetrier{\n\t\tRetrier: NewStopRetrier(),\n\t}\n\trequestRetrier := &testRetrier{\n\t\tRetrier: NewStopRetrier(),\n\t}\n\n\tclient, err := NewClient(\n\t\tSetHttpClient(httpClient),\n\t\tSetHealthcheck(false),\n\t\tSetRetrier(defaultRetrier))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tres, err := client.PerformRequest(context.TODO(), PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    \"/fail\",\n\t\tRetrier: requestRetrier,\n\t})\n\tif err == nil {\n\t\tt.Fatal(\"expected error\")\n\t}\n\tif res != nil {\n\t\tt.Fatal(\"expected no response\")\n\t}\n\tif want, have := int64(0), defaultRetrier.N; want != have {\n\t\tt.Errorf(\"defaultRetrier: expected %d calls; got: %d\", want, have)\n\t}\n\tif want, have := int64(1), requestRetrier.N; want != have {\n\t\tt.Errorf(\"requestRetrier: expected %d calls; got: %d\", want, have)\n\t}\n}\n"
  },
  {
    "path": "retry.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// This file is based on code (c) 2014 Cenk Altı and governed by the MIT license.\n// See https://github.com/cenkalti/backoff for original source.\n\npackage elastic\n\nimport \"time\"\n\n// An Operation is executing by Retry() or RetryNotify().\n// The operation will be retried using a backoff policy if it returns an error.\ntype Operation func() error\n\n// Notify is a notify-on-error function. It receives error returned\n// from an operation.\n//\n// Notice that if the backoff policy stated to stop retrying,\n// the notify function isn't called.\ntype Notify func(error)\n\n// Retry the function f until it does not return error or BackOff stops.\n// f is guaranteed to be run at least once.\n// It is the caller's responsibility to reset b after Retry returns.\n//\n// Retry sleeps the goroutine for the duration returned by BackOff after a\n// failed operation returns.\nfunc Retry(o Operation, b Backoff) error { return RetryNotify(o, b, nil) }\n\n// RetryNotify calls notify function with the error and wait duration\n// for each failed attempt before sleep.\nfunc RetryNotify(operation Operation, b Backoff, notify Notify) error {\n\tvar err error\n\tvar wait time.Duration\n\tvar retry bool\n\tvar n int\n\n\tfor {\n\t\tif err = operation(); err == nil {\n\t\t\treturn nil\n\t\t}\n\n\t\tn++\n\t\twait, retry = b.Next(n)\n\t\tif !retry {\n\t\t\treturn err\n\t\t}\n\n\t\tif notify != nil {\n\t\t\tnotify(err)\n\t\t}\n\n\t\ttime.Sleep(wait)\n\t}\n}\n"
  },
  {
    "path": "retry_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\n// This file is based on code that is (c) 2014 Cenk Altı and governed\n// by the MIT license.\n// See https://github.com/cenkalti/backoff for original source.\n\npackage elastic\n\nimport (\n\t\"errors\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestRetry(t *testing.T) {\n\tconst successOn = 3\n\tvar i = 0\n\n\t// This function is successful on \"successOn\" calls.\n\tf := func() error {\n\t\ti++\n\t\t// t.Logf(\"function is called %d. time\\n\", i)\n\n\t\tif i == successOn {\n\t\t\t// t.Log(\"OK\")\n\t\t\treturn nil\n\t\t}\n\n\t\t// t.Log(\"error\")\n\t\treturn errors.New(\"error\")\n\t}\n\n\tmin := time.Duration(8) * time.Millisecond\n\tmax := time.Duration(256) * time.Millisecond\n\terr := Retry(f, NewExponentialBackoff(min, max))\n\tif err != nil {\n\t\tt.Errorf(\"unexpected error: %s\", err.Error())\n\t}\n\tif i != successOn {\n\t\tt.Errorf(\"invalid number of retries: %d\", i)\n\t}\n}\n"
  },
  {
    "path": "runtime_mappings.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// RuntimeMappings specify fields that are evaluated at query time.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.14/runtime.html\n// for details.\ntype RuntimeMappings map[string]interface{}\n\n// Source deserializes the runtime mappings.\nfunc (m *RuntimeMappings) Source() (interface{}, error) {\n\treturn m, nil\n}\n"
  },
  {
    "path": "runtime_mappings_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestRuntimeMappingsSource(t *testing.T) {\n\trm := RuntimeMappings{\n\t\t\"day_of_week\": map[string]interface{}{\n\t\t\t\"type\": \"keyword\",\n\t\t},\n\t}\n\tsrc, err := rm.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\texpected := `{\"day_of_week\":{\"type\":\"keyword\"}}`\n\tif want, have := expected, string(data); want != have {\n\t\tt.Fatalf(\"want %s, have %s\", want, have)\n\t}\n}\n\nfunc TestRuntimeMappings(t *testing.T) {\n\tclient := setupTestClient(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tctx := context.Background()\n\tindexName := testIndexName\n\n\t// Create index\n\tcreateIndex, err := client.CreateIndex(indexName).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndex)\n\t}\n\n\tmapping := `{\n\t\t\"dynamic\": \"runtime\",\n\t\t\"properties\": {\n\t\t\t\"@timestamp\": {\n\t\t\t\t\"type\":\"date\"\n\t\t\t}\n\t\t},\n\t\t\"runtime\": {\n\t\t\t\"day_of_week\": {\n\t\t\t\t\"type\": \"keyword\",\n\t\t\t\t\"script\": {\n\t\t\t\t\t\"source\": \"emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ROOT))\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}`\n\ttype Doc struct {\n\t\tTimestamp time.Time `json:\"@timestamp\"`\n\t}\n\ttype DynamicDoc struct {\n\t\tTimestamp time.Time `json:\"@timestamp\"`\n\t\tDayOfWeek string    `json:\"day_of_week\"`\n\t}\n\n\t// Create mapping\n\tputResp, err := client.PutMapping().\n\t\tIndex(indexName).\n\t\tBodyString(mapping).\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatalf(\"expected put mapping to succeed; got: %v\", err)\n\t}\n\tif putResp == nil {\n\t\tt.Fatalf(\"expected put mapping response; got: %v\", putResp)\n\t}\n\tif !putResp.Acknowledged {\n\t\tt.Fatalf(\"expected put mapping ack; got: %v\", putResp.Acknowledged)\n\t}\n\n\t// Add a document\n\ttimestamp := time.Date(2021, 1, 17, 23, 24, 25, 26, time.UTC)\n\tindexResult, err := client.Index().\n\t\tIndex(indexName).\n\t\tId(\"1\").\n\t\tBodyJson(&Doc{\n\t\t\tTimestamp: timestamp,\n\t\t}).\n\t\tRefresh(\"wait_for\").\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indexResult == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", indexResult)\n\t}\n\n\t// Execute a search to check for runtime fields\n\tsearchResp, err := client.Search(indexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tDocvalueFields(\"@timestamp\", \"day_of_week\").\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResp == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", searchResp)\n\t}\n\tif want, have := int64(1), searchResp.TotalHits(); want != have {\n\t\tt.Fatalf(\"expected %d search hits, got %d\", want, have)\n\t}\n\n\t// The hit should not have the \"day_of_week\"\n\thit := searchResp.Hits.Hits[0]\n\tvar doc DynamicDoc\n\tif err := json.Unmarshal(hit.Source, &doc); err != nil {\n\t\tt.Fatalf(\"unable to deserialize hit: %v\", err)\n\t}\n\tif want, have := timestamp, doc.Timestamp; want != have {\n\t\tt.Fatalf(\"expected timestamp=%v, got %v\", want, have)\n\t}\n\tif want, have := \"\", doc.DayOfWeek; want != have {\n\t\tt.Fatalf(\"expected day_of_week=%q, got %q\", want, have)\n\t}\n\n\t// The fields should include a \"day_of_week\" of [\"Sunday\"]\n\tdayOfWeekIntfSlice, ok := hit.Fields[\"day_of_week\"].([]interface{})\n\tif !ok {\n\t\tt.Fatalf(\"expected a slice of strings, got %T\", hit.Fields[\"day_of_week\"])\n\t}\n\tif want, have := 1, len(dayOfWeekIntfSlice); want != have {\n\t\tt.Fatalf(\"expected a slice of size %d, have %d\", want, have)\n\t}\n\tdayOfWeek, ok := dayOfWeekIntfSlice[0].(string)\n\tif !ok {\n\t\tt.Fatalf(\"expected an element of string, got %T\", dayOfWeekIntfSlice[0])\n\t}\n\tif want, have := \"Sunday\", dayOfWeek; want != have {\n\t\tt.Fatalf(\"expected day_of_week=%q, have %q\", want, have)\n\t}\n}\n"
  },
  {
    "path": "script.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// Script holds all the parameters necessary to compile or find in cache\n// and then execute a script.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-scripting.html\n// for details of scripting.\ntype Script struct {\n\tscript string\n\ttyp    string\n\tlang   string\n\tparams map[string]interface{}\n}\n\n// NewScript creates and initializes a new Script. By default, it is of\n// type \"inline\". Use NewScriptStored for a stored script (where type is \"id\").\nfunc NewScript(script string) *Script {\n\treturn &Script{\n\t\tscript: script,\n\t\ttyp:    \"inline\",\n\t\tparams: make(map[string]interface{}),\n\t}\n}\n\n// NewScriptInline creates and initializes a new inline script, i.e. code.\nfunc NewScriptInline(script string) *Script {\n\treturn NewScript(script).Type(\"inline\")\n}\n\n// NewScriptStored creates and initializes a new stored script.\nfunc NewScriptStored(script string) *Script {\n\treturn NewScript(script).Type(\"id\")\n}\n\n// Script is either the cache key of the script to be compiled/executed\n// or the actual script source code for inline scripts. For indexed\n// scripts this is the id used in the request. For file scripts this is\n// the file name.\nfunc (s *Script) Script(script string) *Script {\n\ts.script = script\n\treturn s\n}\n\n// Type sets the type of script: \"inline\" or \"id\".\nfunc (s *Script) Type(typ string) *Script {\n\ts.typ = typ\n\treturn s\n}\n\n// Lang sets the language of the script. The default scripting language\n// is Painless (\"painless\").\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-scripting.html\n// for details.\nfunc (s *Script) Lang(lang string) *Script {\n\ts.lang = lang\n\treturn s\n}\n\n// Param adds a key/value pair to the parameters that this script will be executed with.\nfunc (s *Script) Param(name string, value interface{}) *Script {\n\tif s.params == nil {\n\t\ts.params = make(map[string]interface{})\n\t}\n\ts.params[name] = value\n\treturn s\n}\n\n// Params sets the map of parameters this script will be executed with.\nfunc (s *Script) Params(params map[string]interface{}) *Script {\n\ts.params = params\n\treturn s\n}\n\n// Source returns the JSON serializable data for this Script.\nfunc (s *Script) Source() (interface{}, error) {\n\tif s.typ == \"\" && s.lang == \"\" && len(s.params) == 0 {\n\t\treturn s.script, nil\n\t}\n\tsource := make(map[string]interface{})\n\t// Beginning with 6.0, the type can only be \"source\" or \"id\"\n\tif s.typ == \"\" || s.typ == \"inline\" {\n\t\tsrc, err := s.rawScriptSource(s.script)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"source\"] = src\n\t} else {\n\t\tsource[\"id\"] = s.script\n\t}\n\tif s.lang != \"\" {\n\t\tsource[\"lang\"] = s.lang\n\t}\n\tif len(s.params) > 0 {\n\t\tsource[\"params\"] = s.params\n\t}\n\treturn source, nil\n}\n\n// rawScriptSource returns an embeddable script. If it uses a short\n// script form, e.g. \"ctx._source.likes++\" (without the quotes), it\n// is quoted. Otherwise it returns the raw script that will be directly\n// embedded into the JSON data.\nfunc (s *Script) rawScriptSource(script string) (interface{}, error) {\n\tv := strings.TrimSpace(script)\n\tif !strings.HasPrefix(v, \"{\") && !strings.HasPrefix(v, `\"`) {\n\t\tv = fmt.Sprintf(\"%q\", v)\n\t}\n\traw := json.RawMessage(v)\n\treturn &raw, nil\n}\n\n// -- Script Field --\n\n// ScriptField is a single script field.\ntype ScriptField struct {\n\tFieldName string // name of the field\n\n\tscript        *Script\n\tignoreFailure *bool // used in e.g. ScriptSource\n}\n\n// NewScriptField creates and initializes a new ScriptField.\nfunc NewScriptField(fieldName string, script *Script) *ScriptField {\n\treturn &ScriptField{FieldName: fieldName, script: script}\n}\n\n// IgnoreFailure indicates whether to ignore failures. It is used\n// in e.g. ScriptSource.\nfunc (f *ScriptField) IgnoreFailure(ignore bool) *ScriptField {\n\tf.ignoreFailure = &ignore\n\treturn f\n}\n\n// Source returns the serializable JSON for the ScriptField.\nfunc (f *ScriptField) Source() (interface{}, error) {\n\tif f.script == nil {\n\t\treturn nil, errors.New(\"ScriptField expects script\")\n\t}\n\tsource := make(map[string]interface{})\n\tsrc, err := f.script.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsource[\"script\"] = src\n\tif v := f.ignoreFailure; v != nil {\n\t\tsource[\"ignore_failure\"] = *v\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "script_delete.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// DeleteScriptService removes a stored script in Elasticsearch.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-scripting.html\n// for details.\ntype DeleteScriptService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid            string\n\ttimeout       string\n\tmasterTimeout string\n}\n\n// NewDeleteScriptService creates a new DeleteScriptService.\nfunc NewDeleteScriptService(client *Client) *DeleteScriptService {\n\treturn &DeleteScriptService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *DeleteScriptService) Pretty(pretty bool) *DeleteScriptService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *DeleteScriptService) Human(human bool) *DeleteScriptService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *DeleteScriptService) ErrorTrace(errorTrace bool) *DeleteScriptService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *DeleteScriptService) FilterPath(filterPath ...string) *DeleteScriptService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *DeleteScriptService) Header(name string, value string) *DeleteScriptService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *DeleteScriptService) Headers(headers http.Header) *DeleteScriptService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is the script ID.\nfunc (s *DeleteScriptService) Id(id string) *DeleteScriptService {\n\ts.id = id\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *DeleteScriptService) Timeout(timeout string) *DeleteScriptService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout is the timeout for connecting to master.\nfunc (s *DeleteScriptService) MasterTimeout(masterTimeout string) *DeleteScriptService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *DeleteScriptService) buildURL() (string, string, url.Values, error) {\n\tvar (\n\t\terr    error\n\t\tmethod = \"DELETE\"\n\t\tpath   string\n\t)\n\n\tpath, err = uritemplates.Expand(\"/_scripts/{id}\", map[string]string{\n\t\t\"id\": s.id,\n\t})\n\tif err != nil {\n\t\treturn \"\", \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timestamp\", s.masterTimeout)\n\t}\n\treturn method, path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *DeleteScriptService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *DeleteScriptService) Do(ctx context.Context) (*DeleteScriptResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tmethod, path, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  method,\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(DeleteScriptResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// DeleteScriptResponse is the result of deleting a stored script\n// in Elasticsearch.\ntype DeleteScriptResponse struct {\n\tAcknowledgedResponse\n}\n"
  },
  {
    "path": "script_delete_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestDeleteScript(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tscriptID := \"example-delete-script-id\"\n\n\t// Ensure the script does not exist\n\t_, err := client.PerformRequest(\n\t\tcontext.Background(),\n\t\tPerformRequestOptions{\n\t\t\tMethod: \"DELETE\",\n\t\t\tPath:   \"/_scripts/\" + scriptID,\n\t\t})\n\tif err != nil && !IsNotFound(err) {\n\t\tt.Fatal(err)\n\t}\n\n\t// PutScript API\n\tscript := `{\n\t\t\"script\": {\n\t\t\t\"lang\": \"painless\",\n\t\t\t\"source\": \"ctx._source.message = params.new_message\"\n\t\t}\n\t}`\n\tputRes, err := client.PutScript().\n\t\tId(scriptID).\n\t\tBodyString(script).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif putRes == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", putRes)\n\t}\n\tif !putRes.Acknowledged {\n\t\tt.Errorf(\"expected ack for PutScript op; got %v\", putRes.Acknowledged)\n\t}\n\n\t// Must exist now\n\t_, err = client.PerformRequest(\n\t\tcontext.Background(),\n\t\tPerformRequestOptions{\n\t\t\tMethod: \"GET\",\n\t\t\tPath:   \"/_scripts/\" + scriptID,\n\t\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// DeleteScript API\n\tres, err := client.DeleteScript().\n\t\tId(scriptID).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", res)\n\t}\n\tif !res.Acknowledged {\n\t\tt.Errorf(\"expected ack for DeleteScript op; got %v\", res.Acknowledged)\n\t}\n\n\t// Must not exist now\n\t_, err = client.PerformRequest(\n\t\tcontext.Background(),\n\t\tPerformRequestOptions{\n\t\t\tMethod: \"DELETE\",\n\t\t\tPath:   \"/_scripts/\" + scriptID,\n\t\t})\n\tif err != nil && !IsNotFound(err) {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "script_get.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// GetScriptService reads a stored script in Elasticsearch.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-scripting.html\n// for details.\ntype GetScriptService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid string\n}\n\n// NewGetScriptService creates a new GetScriptService.\nfunc NewGetScriptService(client *Client) *GetScriptService {\n\treturn &GetScriptService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *GetScriptService) Pretty(pretty bool) *GetScriptService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *GetScriptService) Human(human bool) *GetScriptService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *GetScriptService) ErrorTrace(errorTrace bool) *GetScriptService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *GetScriptService) FilterPath(filterPath ...string) *GetScriptService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *GetScriptService) Header(name string, value string) *GetScriptService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *GetScriptService) Headers(headers http.Header) *GetScriptService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is the script ID.\nfunc (s *GetScriptService) Id(id string) *GetScriptService {\n\ts.id = id\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *GetScriptService) buildURL() (string, string, url.Values, error) {\n\tvar (\n\t\terr    error\n\t\tmethod = \"GET\"\n\t\tpath   string\n\t)\n\n\tpath, err = uritemplates.Expand(\"/_scripts/{id}\", map[string]string{\n\t\t\"id\": s.id,\n\t})\n\tif err != nil {\n\t\treturn \"\", \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn method, path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *GetScriptService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *GetScriptService) Do(ctx context.Context) (*GetScriptResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tmethod, path, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  method,\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(GetScriptResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// GetScriptResponse is the result of getting a stored script\n// in Elasticsearch.\ntype GetScriptResponse struct {\n\tId     string          `json:\"_id\"`\n\tFound  bool            `json:\"found\"`\n\tScript json.RawMessage `json:\"script\"`\n}\n"
  },
  {
    "path": "script_get_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestGetScript(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tscriptID := \"example-get-script-id\"\n\n\t// Ensure the script does not exist\n\t_, err := client.PerformRequest(\n\t\tcontext.Background(),\n\t\tPerformRequestOptions{\n\t\t\tMethod: \"DELETE\",\n\t\t\tPath:   \"/_scripts/\" + scriptID,\n\t\t})\n\tif err != nil && !IsNotFound(err) {\n\t\tt.Fatal(err)\n\t}\n\n\t// PutScript API\n\tscript := `{\n\t\t\"script\": {\n\t\t\t\"lang\": \"painless\",\n\t\t\t\"source\": \"ctx._source.message = params.new_message\"\n\t\t}\n\t}`\n\tputRes, err := client.PutScript().\n\t\tId(scriptID).\n\t\tBodyString(script).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif putRes == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", putRes)\n\t}\n\tif !putRes.Acknowledged {\n\t\tt.Errorf(\"expected ack for PutScript op; got %v\", putRes.Acknowledged)\n\t}\n\n\t// Must exist now\n\t_, err = client.PerformRequest(\n\t\tcontext.Background(),\n\t\tPerformRequestOptions{\n\t\t\tMethod: \"GET\",\n\t\t\tPath:   \"/_scripts/\" + scriptID,\n\t\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// GetScript API\n\tres, err := client.GetScript().\n\t\tId(scriptID).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", res)\n\t}\n\tif want, have := scriptID, res.Id; want != have {\n\t\tt.Fatalf(\"expected _id = %q; got: %q\", want, have)\n\t}\n\tif want, have := true, res.Found; want != have {\n\t\tt.Fatalf(\"expected found = %v; got: %v\", want, have)\n\t}\n\tif res.Script == nil {\n\t\tt.Fatal(\"expected script; got: nil\")\n\t}\n\toutScript := `{\"lang\":\"painless\",\"source\":\"ctx._source.message = params.new_message\"}`\n\tif want, have := outScript, string(res.Script); want != have {\n\t\tt.Fatalf(\"expected script = %q; got: %q\", want, have)\n\t}\n\n\t// Cleanup\n\tclient.PerformRequest(\n\t\tcontext.Background(),\n\t\tPerformRequestOptions{\n\t\t\tMethod: \"DELETE\",\n\t\t\tPath:   \"/_scripts/\" + scriptID,\n\t\t})\n}\n"
  },
  {
    "path": "script_put.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// PutScriptService adds or updates a stored script in Elasticsearch.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-scripting.html\n// for details.\ntype PutScriptService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid            string\n\tcontext       string\n\ttimeout       string\n\tmasterTimeout string\n\tbodyJson      interface{}\n\tbodyString    string\n}\n\n// NewPutScriptService creates a new PutScriptService.\nfunc NewPutScriptService(client *Client) *PutScriptService {\n\treturn &PutScriptService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *PutScriptService) Pretty(pretty bool) *PutScriptService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *PutScriptService) Human(human bool) *PutScriptService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *PutScriptService) ErrorTrace(errorTrace bool) *PutScriptService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *PutScriptService) FilterPath(filterPath ...string) *PutScriptService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *PutScriptService) Header(name string, value string) *PutScriptService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *PutScriptService) Headers(headers http.Header) *PutScriptService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is the script ID.\nfunc (s *PutScriptService) Id(id string) *PutScriptService {\n\ts.id = id\n\treturn s\n}\n\n// Context specifies the script context (optional).\nfunc (s *PutScriptService) Context(context string) *PutScriptService {\n\ts.context = context\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *PutScriptService) Timeout(timeout string) *PutScriptService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout is the timeout for connecting to master.\nfunc (s *PutScriptService) MasterTimeout(masterTimeout string) *PutScriptService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// BodyJson is the document as a serializable JSON interface.\nfunc (s *PutScriptService) BodyJson(body interface{}) *PutScriptService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is the document encoded as a string.\nfunc (s *PutScriptService) BodyString(body string) *PutScriptService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *PutScriptService) buildURL() (string, string, url.Values, error) {\n\tvar (\n\t\terr    error\n\t\tmethod = \"PUT\"\n\t\tpath   string\n\t)\n\n\tif s.context != \"\" {\n\t\tpath, err = uritemplates.Expand(\"/_scripts/{id}/{context}\", map[string]string{\n\t\t\t\"id\":      s.id,\n\t\t\t\"context\": s.context,\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/_scripts/{id}\", map[string]string{\n\t\t\t\"id\": s.id,\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timestamp\", s.masterTimeout)\n\t}\n\treturn method, path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *PutScriptService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif s.bodyString == \"\" && s.bodyJson == nil {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *PutScriptService) Do(ctx context.Context) (*PutScriptResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tmethod, path, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  method,\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(PutScriptResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// PutScriptResponse is the result of saving a stored script\n// in Elasticsearch.\ntype PutScriptResponse struct {\n\tAcknowledgedResponse\n}\n"
  },
  {
    "path": "script_put_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestPutScript(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tscriptID := \"example-put-script-id\"\n\n\t// Ensure the script does not exist\n\t_, err := client.PerformRequest(\n\t\tcontext.Background(),\n\t\tPerformRequestOptions{\n\t\t\tMethod: \"DELETE\",\n\t\t\tPath:   \"/_scripts/\" + scriptID,\n\t\t})\n\tif err != nil && !IsNotFound(err) {\n\t\tt.Fatal(err)\n\t}\n\n\t// PutScript API\n\tscript := `{\n\t\t\"script\": {\n\t\t\t\"lang\": \"painless\",\n\t\t\t\"source\": \"ctx._source.message = params.new_message\"\n\t\t}\n\t}`\n\tres, err := client.PutScript().\n\t\tId(scriptID).\n\t\tBodyString(script).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", res)\n\t}\n\tif !res.Acknowledged {\n\t\tt.Errorf(\"expected ack for PutScript op; got %v\", res.Acknowledged)\n\t}\n\n\t// Must exist now\n\t_, err = client.PerformRequest(\n\t\tcontext.Background(),\n\t\tPerformRequestOptions{\n\t\t\tMethod: \"GET\",\n\t\t\tPath:   \"/_scripts/\" + scriptID,\n\t\t})\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Cleanup\n\tclient.PerformRequest(\n\t\tcontext.Background(),\n\t\tPerformRequestOptions{\n\t\t\tMethod: \"DELETE\",\n\t\t\tPath:   \"/_scripts/\" + scriptID,\n\t\t})\n}\n"
  },
  {
    "path": "script_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestScriptingDefault(t *testing.T) {\n\tbuilder := NewScript(\"doc['field'].value * 2\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"source\":\"doc['field'].value * 2\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScriptingInline(t *testing.T) {\n\tbuilder := NewScriptInline(\"doc['field'].value * factor\").Param(\"factor\", 2.0)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"params\":{\"factor\":2},\"source\":\"doc['field'].value * factor\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScriptingStored(t *testing.T) {\n\tbuilder := NewScriptStored(\"script-with-id\").Param(\"factor\", 2.0)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"id\":\"script-with-id\",\"params\":{\"factor\":2}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScriptingSource(t *testing.T) {\n\ttests := []struct {\n\t\tInput  string\n\t\tSource string\n\t}{\n\t\t{\n\t\t\tInput:  ``,\n\t\t\tSource: `{\"source\":\"\"}`,\n\t\t},\n\t\t{\n\t\t\tInput:  `doc['field'].value * factor`,\n\t\t\tSource: `{\"source\":\"doc['field'].value * factor\"}`,\n\t\t},\n\t\t{\n\t\t\tInput:  `\"doc['field'].value * factor\"`,\n\t\t\tSource: `{\"source\":\"doc['field'].value * factor\"}`,\n\t\t},\n\t\t{\n\t\t\tInput:  `{\"bool\":{\"filter\":{\"term\":{\"field1\":\"f\"}}}}`,\n\t\t\tSource: `{\"source\":{\"bool\":{\"filter\":{\"term\":{\"field1\":\"f\"}}}}}`,\n\t\t},\n\t}\n\tfor _, tt := range tests {\n\t\tb := NewScriptInline(tt.Input)\n\t\tsrc, err := b.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"unable to generate source for %s: %v\", tt.Input, err)\n\t\t}\n\t\tout, err := json.Marshal(src)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"unable to generate JSON for %s: %v\", tt.Input, err)\n\t\t}\n\t\tif want, have := tt.Source, string(out); want != have {\n\t\t\tt.Fatalf(\"Input=%q: want %s, have %s\", tt.Input, want, have)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "scroll.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\nconst (\n\t// DefaultScrollKeepAlive is the default time a scroll cursor will be kept alive.\n\tDefaultScrollKeepAlive = \"5m\"\n)\n\n// ScrollService iterates over pages of search results from Elasticsearch.\ntype ScrollService struct {\n\tclient  *Client\n\tretrier Retrier\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindices            []string\n\ttypes              []string\n\tkeepAlive          string\n\tbody               interface{}\n\tss                 *SearchSource\n\tsize               *int\n\trouting            string\n\tpreference         string\n\tignoreUnavailable  *bool\n\tignoreThrottled    *bool\n\tallowNoIndices     *bool\n\texpandWildcards    string\n\tmaxResponseSize    int64\n\trestTotalHitsAsInt *bool\n\n\tmu       sync.RWMutex\n\tscrollId string\n}\n\n// NewScrollService initializes and returns a new ScrollService.\nfunc NewScrollService(client *Client) *ScrollService {\n\tbuilder := &ScrollService{\n\t\tclient:    client,\n\t\tss:        NewSearchSource(),\n\t\tkeepAlive: DefaultScrollKeepAlive,\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ScrollService) Pretty(pretty bool) *ScrollService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ScrollService) Human(human bool) *ScrollService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ScrollService) ErrorTrace(errorTrace bool) *ScrollService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ScrollService) FilterPath(filterPath ...string) *ScrollService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ScrollService) Header(name string, value string) *ScrollService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ScrollService) Headers(headers http.Header) *ScrollService {\n\ts.headers = headers\n\treturn s\n}\n\n// Retrier allows to set specific retry logic for this ScrollService.\n// If not specified, it will use the client's default retrier.\nfunc (s *ScrollService) Retrier(retrier Retrier) *ScrollService {\n\ts.retrier = retrier\n\treturn s\n}\n\n// Index sets the name of one or more indices to iterate over.\nfunc (s *ScrollService) Index(indices ...string) *ScrollService {\n\tif s.indices == nil {\n\t\ts.indices = make([]string, 0)\n\t}\n\ts.indices = append(s.indices, indices...)\n\treturn s\n}\n\n// Type sets the name of one or more types to iterate over.\n//\n// Deprecated: Types are in the process of being removed. Instead of using a type, prefer to\n// filter on a field on the document.\nfunc (s *ScrollService) Type(types ...string) *ScrollService {\n\tif s.types == nil {\n\t\ts.types = make([]string, 0)\n\t}\n\ts.types = append(s.types, types...)\n\treturn s\n}\n\n// Scroll is an alias for KeepAlive, the time to keep\n// the cursor alive (e.g. \"5m\" for 5 minutes).\nfunc (s *ScrollService) Scroll(keepAlive string) *ScrollService {\n\ts.keepAlive = keepAlive\n\treturn s\n}\n\n// KeepAlive sets the maximum time after which the cursor will expire.\n// It is \"5m\" by default.\nfunc (s *ScrollService) KeepAlive(keepAlive string) *ScrollService {\n\ts.keepAlive = keepAlive\n\treturn s\n}\n\n// Size specifies the number of documents Elasticsearch should return\n// from each shard, per page.\nfunc (s *ScrollService) Size(size int) *ScrollService {\n\ts.size = &size\n\treturn s\n}\n\n// Highlight allows to highlight search results on one or more fields\nfunc (s *ScrollService) Highlight(highlight *Highlight) *ScrollService {\n\ts.ss = s.ss.Highlight(highlight)\n\treturn s\n}\n\n// Body sets the raw body to send to Elasticsearch. This can be e.g. a string,\n// a map[string]interface{} or anything that can be serialized into JSON.\n// Notice that setting the body disables the use of SearchSource and many\n// other properties of the ScanService.\nfunc (s *ScrollService) Body(body interface{}) *ScrollService {\n\ts.body = body\n\treturn s\n}\n\n// SearchSource sets the search source builder to use with this iterator.\n// Notice that only a certain number of properties can be used when scrolling,\n// e.g. query and sorting.\nfunc (s *ScrollService) SearchSource(searchSource *SearchSource) *ScrollService {\n\ts.ss = searchSource\n\tif s.ss == nil {\n\t\ts.ss = NewSearchSource()\n\t}\n\treturn s\n}\n\n// Query sets the query to perform, e.g. a MatchAllQuery.\nfunc (s *ScrollService) Query(query Query) *ScrollService {\n\ts.ss = s.ss.Query(query)\n\treturn s\n}\n\n// PostFilter is executed as the last filter. It only affects the\n// search hits but not facets. See\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-post-filter.html\n// for details.\nfunc (s *ScrollService) PostFilter(postFilter Query) *ScrollService {\n\ts.ss = s.ss.PostFilter(postFilter)\n\treturn s\n}\n\n// Slice allows slicing the scroll request into several batches.\n// This is supported in Elasticsearch 5.0 or later.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-scroll.html#sliced-scroll\n// for details.\nfunc (s *ScrollService) Slice(sliceQuery Query) *ScrollService {\n\ts.ss = s.ss.Slice(sliceQuery)\n\treturn s\n}\n\n// FetchSource indicates whether the response should contain the stored\n// _source for every hit.\nfunc (s *ScrollService) FetchSource(fetchSource bool) *ScrollService {\n\ts.ss = s.ss.FetchSource(fetchSource)\n\treturn s\n}\n\n// FetchSourceContext indicates how the _source should be fetched.\nfunc (s *ScrollService) FetchSourceContext(fetchSourceContext *FetchSourceContext) *ScrollService {\n\ts.ss = s.ss.FetchSourceContext(fetchSourceContext)\n\treturn s\n}\n\n// Version can be set to true to return a version for each search hit.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-version.html.\nfunc (s *ScrollService) Version(version bool) *ScrollService {\n\ts.ss = s.ss.Version(version)\n\treturn s\n}\n\n// Sort adds a sort order. This can have negative effects on the performance\n// of the scroll operation as Elasticsearch needs to sort first.\nfunc (s *ScrollService) Sort(field string, ascending bool) *ScrollService {\n\ts.ss = s.ss.Sort(field, ascending)\n\treturn s\n}\n\n// SortWithInfo specifies a sort order. Notice that sorting can have a\n// negative impact on scroll performance.\nfunc (s *ScrollService) SortWithInfo(info SortInfo) *ScrollService {\n\ts.ss = s.ss.SortWithInfo(info)\n\treturn s\n}\n\n// SortBy specifies a sort order. Notice that sorting can have a\n// negative impact on scroll performance.\nfunc (s *ScrollService) SortBy(sorter ...Sorter) *ScrollService {\n\ts.ss = s.ss.SortBy(sorter...)\n\treturn s\n}\n\n// TrackTotalHits controls if the total hit count for the query should be tracked.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.1/search-request-track-total-hits.html\n// for details.\nfunc (s *ScrollService) TrackTotalHits(trackTotalHits interface{}) *ScrollService {\n\ts.ss = s.ss.TrackTotalHits(trackTotalHits)\n\treturn s\n}\n\n// RestTotalHitsAsInt indicates whether hits.total should be rendered as an\n// integer or an object in the rest search response.\nfunc (s *ScrollService) RestTotalHitsAsInt(enabled bool) *ScrollService {\n\ts.restTotalHitsAsInt = &enabled\n\treturn s\n}\n\n// Routing is a list of specific routing values to control the shards\n// the search will be executed on.\nfunc (s *ScrollService) Routing(routings ...string) *ScrollService {\n\ts.routing = strings.Join(routings, \",\")\n\treturn s\n}\n\n// Preference sets the preference to execute the search. Defaults to\n// randomize across shards (\"random\"). Can be set to \"_local\" to prefer\n// local shards, \"_primary\" to execute on primary shards only,\n// or a custom value which guarantees that the same order will be used\n// across different requests.\nfunc (s *ScrollService) Preference(preference string) *ScrollService {\n\ts.preference = preference\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether the specified concrete indices\n// should be ignored when unavailable (missing or closed).\nfunc (s *ScrollService) IgnoreUnavailable(ignoreUnavailable bool) *ScrollService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// IgnoreThrottled indicates whether specified concrete, expanded or aliased\n// indices should be ignored when throttled.\nfunc (s *ScrollService) IgnoreThrottled(ignoreThrottled bool) *ScrollService {\n\ts.ignoreThrottled = &ignoreThrottled\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes `_all` string\n// or when no indices have been specified).\nfunc (s *ScrollService) AllowNoIndices(allowNoIndices bool) *ScrollService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *ScrollService) ExpandWildcards(expandWildcards string) *ScrollService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// MaxResponseSize sets an upper limit on the response body size that we accept,\n// to guard against OOM situations.\nfunc (s *ScrollService) MaxResponseSize(maxResponseSize int64) *ScrollService {\n\ts.maxResponseSize = maxResponseSize\n\treturn s\n}\n\n// NoStoredFields indicates that no stored fields should be loaded, resulting in only\n// id and type to be returned per field.\nfunc (s *ScrollService) NoStoredFields() *ScrollService {\n\ts.ss = s.ss.NoStoredFields()\n\treturn s\n}\n\n// StoredField adds a single field to load and return (note, must be stored) as\n// part of the search request. If none are specified, the source of the\n// document will be returned.\nfunc (s *ScrollService) StoredField(fieldName string) *ScrollService {\n\ts.ss = s.ss.StoredField(fieldName)\n\treturn s\n}\n\n// StoredFields\tsets the fields to load and return as part of the search request.\n// If none are specified, the source of the document will be returned.\nfunc (s *ScrollService) StoredFields(fields ...string) *ScrollService {\n\ts.ss = s.ss.StoredFields(fields...)\n\treturn s\n}\n\n// ScrollId specifies the identifier of a scroll in action.\nfunc (s *ScrollService) ScrollId(scrollId string) *ScrollService {\n\ts.mu.Lock()\n\ts.scrollId = scrollId\n\ts.mu.Unlock()\n\treturn s\n}\n\n// Do returns the next search result. It will return io.EOF as error if there\n// are no more search results.\nfunc (s *ScrollService) Do(ctx context.Context) (*SearchResult, error) {\n\ts.mu.RLock()\n\tnextScrollId := s.scrollId\n\ts.mu.RUnlock()\n\tif len(nextScrollId) == 0 {\n\t\treturn s.first(ctx)\n\t}\n\treturn s.next(ctx)\n}\n\n// Clear cancels the current scroll operation. If you don't do this manually,\n// the scroll will be expired automatically by Elasticsearch. You can control\n// how long a scroll cursor is kept alive with the KeepAlive func.\nfunc (s *ScrollService) Clear(ctx context.Context) error {\n\ts.mu.RLock()\n\tscrollId := s.scrollId\n\ts.mu.RUnlock()\n\tif len(scrollId) == 0 {\n\t\treturn nil\n\t}\n\n\tpath := \"/_search/scroll\"\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tbody := struct {\n\t\tScrollId []string `json:\"scroll_id,omitempty\"`\n\t}{\n\t\tScrollId: []string{scrollId},\n\t}\n\n\t_, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tRetrier: s.retrier,\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// -- First --\n\n// first takes the first page of search results.\nfunc (s *ScrollService) first(ctx context.Context) (*SearchResult, error) {\n\t// Get URL and parameters for request\n\tpath, params, err := s.buildFirstURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP request body\n\tbody, err := s.bodyFirst()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:          \"POST\",\n\t\tPath:            path,\n\t\tParams:          params,\n\t\tBody:            body,\n\t\tRetrier:         s.retrier,\n\t\tHeaders:         s.headers,\n\t\tMaxResponseSize: s.maxResponseSize,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SearchResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\ts.mu.Lock()\n\ts.scrollId = ret.ScrollId\n\ts.mu.Unlock()\n\tif ret.Hits == nil || len(ret.Hits.Hits) == 0 {\n\t\treturn ret, io.EOF\n\t}\n\treturn ret, nil\n}\n\n// buildFirstURL builds the URL for retrieving the first page.\nfunc (s *ScrollService) buildFirstURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.indices) == 0 && len(s.types) == 0 {\n\t\tpath = \"/_search\"\n\t} else if len(s.indices) > 0 && len(s.types) == 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_search\", map[string]string{\n\t\t\t\"index\": strings.Join(s.indices, \",\"),\n\t\t})\n\t} else if len(s.indices) == 0 && len(s.types) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_all/{typ}/_search\", map[string]string{\n\t\t\t\"typ\": strings.Join(s.types, \",\"),\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{typ}/_search\", map[string]string{\n\t\t\t\"index\": strings.Join(s.indices, \",\"),\n\t\t\t\"typ\":   strings.Join(s.types, \",\"),\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\t// Always add \"hits._scroll_id\", otherwise we cannot scroll\n\t\tvar found bool\n\t\tfor _, path := range s.filterPath {\n\t\t\tif path == \"_scroll_id\" {\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\ts.filterPath = append(s.filterPath, \"_scroll_id\")\n\t\t}\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.size != nil && *s.size > 0 {\n\t\tparams.Set(\"size\", fmt.Sprintf(\"%d\", *s.size))\n\t}\n\tif len(s.keepAlive) > 0 {\n\t\tparams.Set(\"scroll\", s.keepAlive)\n\t}\n\tif len(s.routing) > 0 {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif len(s.preference) > 0 {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif len(s.expandWildcards) > 0 {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\tif s.ignoreThrottled != nil {\n\t\tparams.Set(\"ignore_throttled\", fmt.Sprintf(\"%v\", *s.ignoreThrottled))\n\t}\n\tif v := s.restTotalHitsAsInt; v != nil {\n\t\tparams.Set(\"rest_total_hits_as_int\", fmt.Sprint(*v))\n\t}\n\n\treturn path, params, nil\n}\n\n// bodyFirst returns the request to fetch the first batch of results.\nfunc (s *ScrollService) bodyFirst() (interface{}, error) {\n\tvar err error\n\tvar body interface{}\n\n\tif s.body != nil {\n\t\tbody = s.body\n\t} else {\n\t\t// Use _doc sort by default if none is specified\n\t\tif !s.ss.hasSort() {\n\t\t\t// Use efficient sorting when no user-defined query/body is specified\n\t\t\ts.ss = s.ss.SortBy(SortByDoc{})\n\t\t}\n\n\t\t// Body from search source\n\t\tbody, err = s.ss.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn body, nil\n}\n\n// -- Next --\n\nfunc (s *ScrollService) next(ctx context.Context) (*SearchResult, error) {\n\t// Get URL for request\n\tpath, params, err := s.buildNextURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tbody, err := s.bodyNext()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:          \"POST\",\n\t\tPath:            path,\n\t\tParams:          params,\n\t\tBody:            body,\n\t\tRetrier:         s.retrier,\n\t\tHeaders:         s.headers,\n\t\tMaxResponseSize: s.maxResponseSize,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SearchResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\ts.mu.Lock()\n\ts.scrollId = ret.ScrollId\n\ts.mu.Unlock()\n\tif ret.Hits == nil || len(ret.Hits.Hits) == 0 {\n\t\treturn ret, io.EOF\n\t}\n\treturn ret, nil\n}\n\n// buildNextURL builds the URL for the operation.\nfunc (s *ScrollService) buildNextURL() (string, url.Values, error) {\n\tpath := \"/_search/scroll\"\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\t// Always add \"hits._scroll_id\", otherwise we cannot scroll\n\t\tvar found bool\n\t\tfor _, path := range s.filterPath {\n\t\t\tif path == \"_scroll_id\" {\n\t\t\t\tfound = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif !found {\n\t\t\ts.filterPath = append(s.filterPath, \"_scroll_id\")\n\t\t}\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.restTotalHitsAsInt; v != nil {\n\t\tparams.Set(\"rest_total_hits_as_int\", fmt.Sprint(*v))\n\t}\n\n\treturn path, params, nil\n}\n\n// body returns the request to fetch the next batch of results.\nfunc (s *ScrollService) bodyNext() (interface{}, error) {\n\ts.mu.RLock()\n\tbody := struct {\n\t\tScroll   string `json:\"scroll\"`\n\t\tScrollId string `json:\"scroll_id,omitempty\"`\n\t}{\n\t\tScroll:   s.keepAlive,\n\t\tScrollId: s.scrollId,\n\t}\n\ts.mu.RUnlock()\n\treturn body, nil\n}\n\n// DocvalueField adds a single field to load from the field data cache\n// and return as part of the search.\nfunc (s *ScrollService) DocvalueField(docvalueField string) *ScrollService {\n\ts.ss = s.ss.DocvalueField(docvalueField)\n\treturn s\n}\n\n// DocvalueFieldWithFormat adds a single field to load from the field data cache\n// and return as part of the search.\nfunc (s *ScrollService) DocvalueFieldWithFormat(docvalueField DocvalueField) *ScrollService {\n\ts.ss = s.ss.DocvalueFieldWithFormat(docvalueField)\n\treturn s\n}\n\n// DocvalueFields adds one or more fields to load from the field data cache\n// and return as part of the search.\nfunc (s *ScrollService) DocvalueFields(docvalueFields ...string) *ScrollService {\n\ts.ss = s.ss.DocvalueFields(docvalueFields...)\n\treturn s\n}\n\n// DocvalueFieldsWithFormat adds one or more fields to load from the field data cache\n// and return as part of the search.\nfunc (s *ScrollService) DocvalueFieldsWithFormat(docvalueFields ...DocvalueField) *ScrollService {\n\ts.ss = s.ss.DocvalueFieldsWithFormat(docvalueFields...)\n\treturn s\n}\n"
  },
  {
    "path": "scroll_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"io\"\n\t_ \"net/http\"\n\t\"net/url\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc TestScroll(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t)\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Should return all documents. Just don't call Do yet!\n\tsvc := client.Scroll(testIndexName).Size(1)\n\n\tpages := 0\n\tdocs := 0\n\n\tfor {\n\t\tres, err := svc.Do(context.TODO())\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res == nil {\n\t\t\tt.Fatal(\"expected results != nil; got nil\")\n\t\t}\n\t\tif res.Hits == nil {\n\t\t\tt.Fatal(\"expected results.Hits != nil; got nil\")\n\t\t}\n\t\tif want, have := int64(3), res.TotalHits(); want != have {\n\t\t\tt.Fatalf(\"expected results.TotalHits() = %d; got %d\", want, have)\n\t\t}\n\t\tif want, have := 1, len(res.Hits.Hits); want != have {\n\t\t\tt.Fatalf(\"expected len(results.Hits.Hits) = %d; got %d\", want, have)\n\t\t}\n\n\t\tpages++\n\n\t\tfor _, hit := range res.Hits.Hits {\n\t\t\tif hit.Index != testIndexName {\n\t\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t\t}\n\t\t\titem := make(map[string]interface{})\n\t\t\terr := json.Unmarshal(hit.Source, &item)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdocs++\n\t\t}\n\n\t\tif len(res.ScrollId) == 0 {\n\t\t\tt.Fatalf(\"expected scrollId in results; got %q\", res.ScrollId)\n\t\t}\n\t}\n\n\tif want, have := 3, pages; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d pages; got %d\", want, have)\n\t}\n\tif want, have := 3, docs; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d hits; got %d\", want, have)\n\t}\n\n\terr = svc.Clear(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = svc.Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatal(\"expected to fail\")\n\t}\n}\n\nfunc TestScrollWithQueryAndSort(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\t// client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Create a scroll service that returns tweets from user olivere\n\t// and returns them sorted by \"message\", in reverse order.\n\t//\n\t// Just don't call Do yet!\n\tsvc := client.Scroll(testIndexName).\n\t\tQuery(NewTermQuery(\"user\", \"olivere\")).\n\t\tSort(\"message\", false).\n\t\tSize(1).\n\t\tTrackTotalHits(true)\n\n\tdocs := 0\n\tpages := 0\n\tfor {\n\t\tres, err := svc.Do(context.TODO())\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res == nil {\n\t\t\tt.Fatal(\"expected results != nil; got nil\")\n\t\t}\n\t\tif res.Hits == nil {\n\t\t\tt.Fatal(\"expected results.Hits != nil; got nil\")\n\t\t}\n\t\tif want, have := int64(2), res.TotalHits(); want != have {\n\t\t\tt.Fatalf(\"expected results.TotalHits() = %d; got %d\", want, have)\n\t\t}\n\t\tif want, have := 1, len(res.Hits.Hits); want != have {\n\t\t\tt.Fatalf(\"expected len(results.Hits.Hits) = %d; got %d\", want, have)\n\t\t}\n\n\t\tpages++\n\n\t\tfor _, hit := range res.Hits.Hits {\n\t\t\tif hit.Index != testIndexName {\n\t\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t\t}\n\t\t\titem := make(map[string]interface{})\n\t\t\terr := json.Unmarshal(hit.Source, &item)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdocs++\n\t\t}\n\t}\n\n\tif want, have := 2, pages; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d pages; got %d\", want, have)\n\t}\n\tif want, have := 2, docs; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d hits; got %d\", want, have)\n\t}\n}\n\nfunc TestScrollWithBody(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t)\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\", Retweets: 4}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\", Retweets: 10}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\", Retweets: 3}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Test with simple strings and a map\n\tvar tests = []struct {\n\t\tBody              interface{}\n\t\tExpectedTotalHits int64\n\t\tExpectedDocs      int\n\t\tExpectedPages     int\n\t}{\n\t\t{\n\t\t\tBody:              `{\"query\":{\"match_all\":{}}}`,\n\t\t\tExpectedTotalHits: 3,\n\t\t\tExpectedDocs:      3,\n\t\t\tExpectedPages:     3,\n\t\t},\n\t\t{\n\t\t\tBody:              `{\"query\":{\"term\":{\"user\":\"olivere\"}},\"sort\":[\"_doc\"]}`,\n\t\t\tExpectedTotalHits: 2,\n\t\t\tExpectedDocs:      2,\n\t\t\tExpectedPages:     2,\n\t\t},\n\t\t{\n\t\t\tBody:              `{\"query\":{\"term\":{\"user\":\"olivere\"}},\"sort\":[{\"retweets\":\"desc\"}]}`,\n\t\t\tExpectedTotalHits: 2,\n\t\t\tExpectedDocs:      2,\n\t\t\tExpectedPages:     2,\n\t\t},\n\t\t{\n\t\t\tBody: map[string]interface{}{\n\t\t\t\t\"query\": map[string]interface{}{\n\t\t\t\t\t\"term\": map[string]interface{}{\n\t\t\t\t\t\t\"user\": \"olivere\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"sort\": []interface{}{\"_doc\"},\n\t\t\t},\n\t\t\tExpectedTotalHits: 2,\n\t\t\tExpectedDocs:      2,\n\t\t\tExpectedPages:     2,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\t// Should return all documents. Just don't call Do yet!\n\t\tsvc := client.Scroll(testIndexName).Size(1).Body(tt.Body)\n\n\t\tpages := 0\n\t\tdocs := 0\n\n\t\tfor {\n\t\t\tres, err := svc.Do(context.TODO())\n\t\t\tif err == io.EOF {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tif res == nil {\n\t\t\t\tt.Fatalf(\"#%d: expected results != nil; got nil\", i)\n\t\t\t}\n\t\t\tif res.Hits == nil {\n\t\t\t\tt.Fatalf(\"#%d: expected results.Hits != nil; got nil\", i)\n\t\t\t}\n\t\t\tif want, have := tt.ExpectedTotalHits, res.TotalHits(); want != have {\n\t\t\t\tt.Fatalf(\"#%d: expected results.TotalHits() = %d; got %d\", i, want, have)\n\t\t\t}\n\t\t\tif want, have := 1, len(res.Hits.Hits); want != have {\n\t\t\t\tt.Fatalf(\"#%d: expected len(results.Hits.Hits) = %d; got %d\", i, want, have)\n\t\t\t}\n\n\t\t\tpages++\n\n\t\t\tfor _, hit := range res.Hits.Hits {\n\t\t\t\tif hit.Index != testIndexName {\n\t\t\t\t\tt.Fatalf(\"#%d: expected SearchResult.Hits.Hit.Index = %q; got %q\", i, testIndexName, hit.Index)\n\t\t\t\t}\n\t\t\t\titem := make(map[string]interface{})\n\t\t\t\terr := json.Unmarshal(hit.Source, &item)\n\t\t\t\tif err != nil {\n\t\t\t\t\tt.Fatalf(\"#%d: %v\", i, err)\n\t\t\t\t}\n\t\t\t\tdocs++\n\t\t\t}\n\n\t\t\tif len(res.ScrollId) == 0 {\n\t\t\t\tt.Fatalf(\"#%d: expected scrollId in results; got %q\", i, res.ScrollId)\n\t\t\t}\n\t\t}\n\n\t\tif want, have := tt.ExpectedPages, pages; want != have {\n\t\t\tt.Fatalf(\"#%d: expected to retrieve %d pages; got %d\", i, want, have)\n\t\t}\n\t\tif want, have := tt.ExpectedDocs, docs; want != have {\n\t\t\tt.Fatalf(\"#%d: expected to retrieve %d hits; got %d\", i, want, have)\n\t\t}\n\n\t\terr = svc.Clear(context.TODO())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: failed to clear scroll context: %v\", i, err)\n\t\t}\n\n\t\t_, err = svc.Do(context.TODO())\n\t\tif err == nil {\n\t\t\tt.Fatalf(\"#%d: expected to fail\", i)\n\t\t}\n\t}\n}\n\nfunc TestScrollWithSlice(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Should return all documents. Just don't call Do yet!\n\tsliceQuery := NewSliceQuery().Id(0).Max(2)\n\tsvc := client.Scroll(testIndexName).Slice(sliceQuery).Size(1)\n\n\tpages := 0\n\tdocs := 0\n\n\tfor {\n\t\tres, err := svc.Do(context.TODO())\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res == nil {\n\t\t\tt.Fatal(\"expected results != nil; got nil\")\n\t\t}\n\t\tif res.Hits == nil {\n\t\t\tt.Fatal(\"expected results.Hits != nil; got nil\")\n\t\t}\n\n\t\tpages++\n\n\t\tfor _, hit := range res.Hits.Hits {\n\t\t\tif hit.Index != testIndexName {\n\t\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t\t}\n\t\t\titem := make(map[string]interface{})\n\t\t\terr := json.Unmarshal(hit.Source, &item)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdocs++\n\t\t}\n\n\t\tif len(res.ScrollId) == 0 {\n\t\t\tt.Fatalf(\"expected scrollId in results; got %q\", res.ScrollId)\n\t\t}\n\t}\n\n\tif pages == 0 {\n\t\tt.Fatal(\"expected to retrieve some pages\")\n\t}\n\tif docs == 0 {\n\t\tt.Fatal(\"expected to retrieve some hits\")\n\t}\n\n\tif err := svc.Clear(context.TODO()); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif _, err := svc.Do(context.TODO()); err == nil {\n\t\tt.Fatal(\"expected to fail\")\n\t}\n}\n\nfunc TestScrollWithMaxResponseSize(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\", Retweets: 3}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\", Retweets: 4}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Test response size error on first scroll request (first response is 418 bytes)\n\tsvc := client.Scroll(testIndexName).Size(1).MaxResponseSize(400)\n\t_, err = svc.Do(context.TODO())\n\tif err != ErrResponseSize {\n\t\tt.Fatalf(\"expected response size error\")\n\t}\n\n\t// Test response size error on second scroll request (first response is 418 bytes, second is 439 bytes)\n\tsvc = client.Scroll(testIndexName).Size(1).MaxResponseSize(16384)\n\t_, err = svc.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tsvc = client.Scroll(testIndexName).Size(1).MaxResponseSize(400)\n\t_, err = svc.Do(context.TODO())\n\tif err != ErrResponseSize {\n\t\tt.Fatalf(\"expected response size error\")\n\t}\n}\n\nfunc TestScrollWithFilterPath(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t)\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Should return all documents. Just don't call Do yet!\n\t// Notice that we don't have to add \"_scroll_id\" to the FilterPath here:\n\t// It's been added automatically by the ScrollService.\n\tsvc := client.Scroll(testIndexName).Size(1).\n\t\tFilterPath(\"hits.total\", \"hits.hits._index\", \"hits.hits._id\", \"hits.hits._source\")\n\n\tpages := 0\n\tdocs := 0\n\n\tfor {\n\t\tres, err := svc.Do(context.TODO())\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res == nil {\n\t\t\tt.Fatal(\"expected results != nil; got nil\")\n\t\t}\n\t\tif res.Hits == nil {\n\t\t\tt.Fatal(\"expected results.Hits != nil; got nil\")\n\t\t}\n\t\tif want, have := int64(3), res.TotalHits(); want != have {\n\t\t\tt.Fatalf(\"expected results.TotalHits() = %d; got %d\", want, have)\n\t\t}\n\t\tif want, have := 1, len(res.Hits.Hits); want != have {\n\t\t\tt.Fatalf(\"expected len(results.Hits.Hits) = %d; got %d\", want, have)\n\t\t}\n\n\t\tpages++\n\n\t\tfor _, hit := range res.Hits.Hits {\n\t\t\tif hit.Index != testIndexName {\n\t\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t\t}\n\t\t\titem := make(map[string]interface{})\n\t\t\terr := json.Unmarshal(hit.Source, &item)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdocs++\n\t\t}\n\n\t\tif len(res.ScrollId) == 0 {\n\t\t\tt.Fatalf(\"expected scrollId in results; got %q\", res.ScrollId)\n\t\t}\n\n\t\t// Ensure we don't have \"_scroll_id\" in the query string more than once\n\t\tvar scrollIdCount int\n\t\tfor _, path := range svc.filterPath {\n\t\t\tif path == \"_scroll_id\" {\n\t\t\t\tscrollIdCount++\n\t\t\t}\n\t\t}\n\t\tif want, have := 1, scrollIdCount; want != have {\n\t\t\tt.Fatalf(\"expected _scroll_id to occur %d time(s), got %d\", want, have)\n\t\t}\n\t}\n\n\tif want, have := 3, pages; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d pages; got %d\", want, have)\n\t}\n\tif want, have := 3, docs; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d hits; got %d\", want, have)\n\t}\n\n\terr = svc.Clear(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = svc.Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatal(\"expected to fail\")\n\t}\n}\n\nfunc TestScrollWithFilterPathKeepingContext(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t)\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Should return all documents. Just don't call Do yet!\n\t// Notice that we don't have to add \"_scroll_id\" to the FilterPath here:\n\t// It's been added automatically by the ScrollService.\n\tsvc := client.Scroll(testIndexName).Size(1).\n\t\tFilterPath(\"hits.total\", \"hits.hits._index\", \"hits.hits._id\")\n\n\tpages := 0\n\tdocs := 0\n\n\tfor {\n\t\tres, err := svc.Do(context.TODO())\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res == nil {\n\t\t\tt.Fatal(\"expected results != nil; got nil\")\n\t\t}\n\t\tif res.Hits == nil {\n\t\t\tt.Fatal(\"expected results.Hits != nil; got nil\")\n\t\t}\n\t\tif want, have := int64(3), res.TotalHits(); want != have {\n\t\t\tt.Fatalf(\"expected results.TotalHits() = %d; got %d\", want, have)\n\t\t}\n\t\tif want, have := 1, len(res.Hits.Hits); want != have {\n\t\t\tt.Fatalf(\"expected len(results.Hits.Hits) = %d; got %d\", want, have)\n\t\t}\n\n\t\tpages++\n\n\t\tfor _, hit := range res.Hits.Hits {\n\t\t\tif hit.Index != testIndexName {\n\t\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t\t}\n\t\t\tif hit.Source != nil {\n\t\t\t\tt.Fatal(\"expected SearchResult.Hits.Hit.Source = nil\")\n\t\t\t}\n\t\t\tdocs++\n\t\t}\n\n\t\tif len(res.ScrollId) == 0 {\n\t\t\tt.Fatalf(\"expected scrollId in results; got %q\", res.ScrollId)\n\t\t}\n\t}\n\n\tif want, have := 3, pages; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d pages; got %d\", want, have)\n\t}\n\tif want, have := 3, docs; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d hits; got %d\", want, have)\n\t}\n\n\terr = svc.Clear(context.TODO())\n\tif err != nil && !IsNotFound(err) {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = svc.Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatal(\"expected to fail\")\n\t}\n}\n\nfunc TestScrollTotalHits(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndLog(t)\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Should return all documents with ES 6.x compatible total hits. Just don't call Do yet!\n\tsvc := client.Scroll(testIndexName).Size(1).RestTotalHitsAsInt(true)\n\n\tpages := 0\n\tdocs := 0\n\n\tfor {\n\t\tres, err := svc.Do(context.TODO())\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res == nil {\n\t\t\tt.Fatal(\"expected results != nil; got nil\")\n\t\t}\n\t\tif res.Hits == nil {\n\t\t\tt.Fatal(\"expected results.Hits != nil; got nil\")\n\t\t}\n\t\tif want, have := int64(3), res.TotalHits(); want != have {\n\t\t\tt.Fatalf(\"expected results.TotalHits() = %d; got %d\", want, have)\n\t\t}\n\t\tif want, have := 1, len(res.Hits.Hits); want != have {\n\t\t\tt.Fatalf(\"expected len(results.Hits.Hits) = %d; got %d\", want, have)\n\t\t}\n\n\t\tpages++\n\n\t\tfor _, hit := range res.Hits.Hits {\n\t\t\tif hit.Index != testIndexName {\n\t\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t\t}\n\t\t\titem := make(map[string]interface{})\n\t\t\terr := json.Unmarshal(hit.Source, &item)\n\t\t\tif err != nil {\n\t\t\t\tt.Fatal(err)\n\t\t\t}\n\t\t\tdocs++\n\t\t}\n\n\t\tif len(res.ScrollId) == 0 {\n\t\t\tt.Fatalf(\"expected scrollId in results; got %q\", res.ScrollId)\n\t\t}\n\t}\n\n\tif want, have := 3, pages; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d pages; got %d\", want, have)\n\t}\n\tif want, have := 3, docs; want != have {\n\t\tt.Fatalf(\"expected to retrieve %d hits; got %d\", want, have)\n\t}\n\n\terr = svc.Clear(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = svc.Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatal(\"expected to fail\")\n\t}\n}\n\nfunc TestScrollBuilder(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t)\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tService        *ScrollService\n\t\tExpectedPath   string\n\t\tExpectedParams url.Values\n\t\tExpectedBody   string\n\t}{\n\t\t// #0: FetchSourceContext in ScrollService\n\t\t{\n\t\t\tService: client.\n\t\t\t\tScroll(testIndexName).\n\t\t\t\tSearchSource(\n\t\t\t\t\tNewSearchSource().Query(NewMatchAllQuery()),\n\t\t\t\t).\n\t\t\t\tFetchSourceContext(NewFetchSourceContext(false).Include(\"foo\")).\n\t\t\t\tSize(600),\n\t\t\tExpectedPath: \"/elastic-test/_search\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"scroll\": []string{\"5m\"},\n\t\t\t\t\"size\":   []string{\"600\"},\n\t\t\t},\n\t\t\tExpectedBody: `{\"_source\":false,\"query\":{\"match_all\":{}},\"sort\":[\"_doc\"]}`,\n\t\t},\n\t\t// #1: FetchSourceContext in SearchSource\n\t\t{\n\t\t\tService: client.Scroll(testIndexName).\n\t\t\t\tSearchSource(\n\t\t\t\t\tNewSearchSource().Query(\n\t\t\t\t\t\tNewMatchAllQuery(),\n\t\t\t\t\t).\n\t\t\t\t\t\tFetchSourceContext(NewFetchSourceContext(false).Include(\"foo\")),\n\t\t\t\t).\n\t\t\t\tSize(600),\n\t\t\tExpectedPath: \"/elastic-test/_search\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"scroll\": []string{\"5m\"},\n\t\t\t\t\"size\":   []string{\"600\"},\n\t\t\t},\n\t\t\tExpectedBody: `{\"_source\":false,\"query\":{\"match_all\":{}},\"sort\":[\"_doc\"]}`,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\t// Get URL and parameters for request\n\t\tpath, params, err := tt.Service.buildFirstURL()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: %v\", i, err)\n\t\t}\n\t\tif want, have := tt.ExpectedPath, path; want != have {\n\t\t\tt.Fatalf(\"#%d: want Path=%q, have %q\", i, want, have)\n\t\t}\n\t\tif want, have := tt.ExpectedParams, params; !cmp.Equal(want, have) {\n\t\t\tt.Fatalf(\"#%d: invalid Params; expected:\\ndiff=%v\", i, cmp.Diff(want, have))\n\t\t}\n\n\t\t// Get HTTP request body\n\t\tbody, err := tt.Service.bodyFirst()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tjs, err := json.Marshal(body)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif want, have := tt.ExpectedBody, string(js); !cmp.Equal(want, have) {\n\t\t\tt.Fatalf(\"#%d: want Body=%s, have %s\\ndiff=%v\", i, want, have, cmp.Diff(want, have))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "search.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// Search for documents in Elasticsearch.\ntype SearchService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tsearchSource               *SearchSource // q\n\tsource                     interface{}\n\tsearchType                 string // search_type\n\tindex                      []string\n\ttyp                        []string\n\trouting                    string // routing\n\tpreference                 string // preference\n\trequestCache               *bool  // request_cache\n\tignoreUnavailable          *bool  // ignore_unavailable\n\tignoreThrottled            *bool  // ignore_throttled\n\tallowNoIndices             *bool  // allow_no_indices\n\texpandWildcards            string // expand_wildcards\n\tlenient                    *bool  // lenient\n\tmaxResponseSize            int64\n\tallowPartialSearchResults  *bool // allow_partial_search_results\n\ttypedKeys                  *bool // typed_keys\n\tseqNoPrimaryTerm           *bool // seq_no_primary_term\n\tbatchedReduceSize          *int  // batched_reduce_size\n\tmaxConcurrentShardRequests *int  // max_concurrent_shard_requests\n\tpreFilterShardSize         *int  // pre_filter_shard_size\n\trestTotalHitsAsInt         *bool // rest_total_hits_as_int\n\n\tccsMinimizeRoundtrips *bool // ccs_minimize_roundtrips\n\n}\n\n// NewSearchService creates a new service for searching in Elasticsearch.\nfunc NewSearchService(client *Client) *SearchService {\n\tbuilder := &SearchService{\n\t\tclient:       client,\n\t\tsearchSource: NewSearchSource(),\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SearchService) Pretty(pretty bool) *SearchService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SearchService) Human(human bool) *SearchService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SearchService) ErrorTrace(errorTrace bool) *SearchService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SearchService) FilterPath(filterPath ...string) *SearchService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SearchService) Header(name string, value string) *SearchService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SearchService) Headers(headers http.Header) *SearchService {\n\ts.headers = headers\n\treturn s\n}\n\n// SearchSource sets the search source builder to use with this service.\nfunc (s *SearchService) SearchSource(searchSource *SearchSource) *SearchService {\n\ts.searchSource = searchSource\n\tif s.searchSource == nil {\n\t\ts.searchSource = NewSearchSource()\n\t}\n\treturn s\n}\n\n// Source allows the user to set the request body manually without using\n// any of the structs and interfaces in Elastic.\nfunc (s *SearchService) Source(source interface{}) *SearchService {\n\ts.source = source\n\treturn s\n}\n\n// Index sets the names of the indices to use for search.\nfunc (s *SearchService) Index(index ...string) *SearchService {\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// Type adds search restrictions for a list of types.\n//\n// Deprecated: Types are in the process of being removed. Instead of using a type, prefer to\n// filter on a field on the document.\nfunc (s *SearchService) Type(typ ...string) *SearchService {\n\ts.typ = append(s.typ, typ...)\n\treturn s\n}\n\n// Timeout sets the timeout to use, e.g. \"1s\" or \"1000ms\".\nfunc (s *SearchService) Timeout(timeout string) *SearchService {\n\ts.searchSource = s.searchSource.Timeout(timeout)\n\treturn s\n}\n\n// Profile sets the Profile API flag on the search source.\n// When enabled, a search executed by this service will return query\n// profiling data.\nfunc (s *SearchService) Profile(profile bool) *SearchService {\n\ts.searchSource = s.searchSource.Profile(profile)\n\treturn s\n}\n\n// Collapse adds field collapsing.\nfunc (s *SearchService) Collapse(collapse *CollapseBuilder) *SearchService {\n\ts.searchSource = s.searchSource.Collapse(collapse)\n\treturn s\n}\n\n// PointInTime specifies an optional PointInTime to be used in the context\n// of this search.\nfunc (s *SearchService) PointInTime(pointInTime *PointInTime) *SearchService {\n\ts.searchSource = s.searchSource.PointInTime(pointInTime)\n\treturn s\n}\n\n// RuntimeMappings specifies optional runtime mappings.\nfunc (s *SearchService) RuntimeMappings(runtimeMappings RuntimeMappings) *SearchService {\n\ts.searchSource = s.searchSource.RuntimeMappings(runtimeMappings)\n\treturn s\n}\n\n// TimeoutInMillis sets the timeout in milliseconds.\nfunc (s *SearchService) TimeoutInMillis(timeoutInMillis int) *SearchService {\n\ts.searchSource = s.searchSource.TimeoutInMillis(timeoutInMillis)\n\treturn s\n}\n\n// TerminateAfter specifies the maximum number of documents to collect for\n// each shard, upon reaching which the query execution will terminate early.\nfunc (s *SearchService) TerminateAfter(terminateAfter int) *SearchService {\n\ts.searchSource = s.searchSource.TerminateAfter(terminateAfter)\n\treturn s\n}\n\n// SearchType sets the search operation type. Valid values are:\n// \"dfs_query_then_fetch\" and \"query_then_fetch\".\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-search-type.html\n// for details.\nfunc (s *SearchService) SearchType(searchType string) *SearchService {\n\ts.searchType = searchType\n\treturn s\n}\n\n// Routing is a list of specific routing values to control the shards\n// the search will be executed on.\nfunc (s *SearchService) Routing(routings ...string) *SearchService {\n\ts.routing = strings.Join(routings, \",\")\n\treturn s\n}\n\n// Preference sets the preference to execute the search. Defaults to\n// randomize across shards (\"random\"). Can be set to \"_local\" to prefer\n// local shards, \"_primary\" to execute on primary shards only,\n// or a custom value which guarantees that the same order will be used\n// across different requests.\nfunc (s *SearchService) Preference(preference string) *SearchService {\n\ts.preference = preference\n\treturn s\n}\n\n// RequestCache indicates whether the cache should be used for this\n// request or not, defaults to index level setting.\nfunc (s *SearchService) RequestCache(requestCache bool) *SearchService {\n\ts.requestCache = &requestCache\n\treturn s\n}\n\n// Query sets the query to perform, e.g. MatchAllQuery.\nfunc (s *SearchService) Query(query Query) *SearchService {\n\ts.searchSource = s.searchSource.Query(query)\n\treturn s\n}\n\n// PostFilter will be executed after the query has been executed and\n// only affects the search hits, not the aggregations.\n// This filter is always executed as the last filtering mechanism.\nfunc (s *SearchService) PostFilter(postFilter Query) *SearchService {\n\ts.searchSource = s.searchSource.PostFilter(postFilter)\n\treturn s\n}\n\n// FetchSource indicates whether the response should contain the stored\n// _source for every hit.\nfunc (s *SearchService) FetchSource(fetchSource bool) *SearchService {\n\ts.searchSource = s.searchSource.FetchSource(fetchSource)\n\treturn s\n}\n\n// FetchSourceContext indicates how the _source should be fetched.\nfunc (s *SearchService) FetchSourceContext(fetchSourceContext *FetchSourceContext) *SearchService {\n\ts.searchSource = s.searchSource.FetchSourceContext(fetchSourceContext)\n\treturn s\n}\n\n// Highlight adds highlighting to the search.\nfunc (s *SearchService) Highlight(highlight *Highlight) *SearchService {\n\ts.searchSource = s.searchSource.Highlight(highlight)\n\treturn s\n}\n\n// GlobalSuggestText defines the global text to use with all suggesters.\n// This avoids repetition.\nfunc (s *SearchService) GlobalSuggestText(globalText string) *SearchService {\n\ts.searchSource = s.searchSource.GlobalSuggestText(globalText)\n\treturn s\n}\n\n// Suggester adds a suggester to the search.\nfunc (s *SearchService) Suggester(suggester Suggester) *SearchService {\n\ts.searchSource = s.searchSource.Suggester(suggester)\n\treturn s\n}\n\n// Aggregation adds an aggreation to perform as part of the search.\nfunc (s *SearchService) Aggregation(name string, aggregation Aggregation) *SearchService {\n\ts.searchSource = s.searchSource.Aggregation(name, aggregation)\n\treturn s\n}\n\n// MinScore sets the minimum score below which docs will be filtered out.\nfunc (s *SearchService) MinScore(minScore float64) *SearchService {\n\ts.searchSource = s.searchSource.MinScore(minScore)\n\treturn s\n}\n\n// From index to start the search from. Defaults to 0.\nfunc (s *SearchService) From(from int) *SearchService {\n\ts.searchSource = s.searchSource.From(from)\n\treturn s\n}\n\n// Size is the number of search hits to return. Defaults to 10.\nfunc (s *SearchService) Size(size int) *SearchService {\n\ts.searchSource = s.searchSource.Size(size)\n\treturn s\n}\n\n// Explain indicates whether each search hit should be returned with\n// an explanation of the hit (ranking).\nfunc (s *SearchService) Explain(explain bool) *SearchService {\n\ts.searchSource = s.searchSource.Explain(explain)\n\treturn s\n}\n\n// Version indicates whether each search hit should be returned with\n// a version associated to it.\nfunc (s *SearchService) Version(version bool) *SearchService {\n\ts.searchSource = s.searchSource.Version(version)\n\treturn s\n}\n\n// Sort adds a sort order.\nfunc (s *SearchService) Sort(field string, ascending bool) *SearchService {\n\ts.searchSource = s.searchSource.Sort(field, ascending)\n\treturn s\n}\n\n// SortWithInfo adds a sort order.\nfunc (s *SearchService) SortWithInfo(info SortInfo) *SearchService {\n\ts.searchSource = s.searchSource.SortWithInfo(info)\n\treturn s\n}\n\n// SortBy adds a sort order.\nfunc (s *SearchService) SortBy(sorter ...Sorter) *SearchService {\n\ts.searchSource = s.searchSource.SortBy(sorter...)\n\treturn s\n}\n\n// DocvalueField adds a single field to load from the field data cache\n// and return as part of the search.\nfunc (s *SearchService) DocvalueField(docvalueField string) *SearchService {\n\ts.searchSource = s.searchSource.DocvalueField(docvalueField)\n\treturn s\n}\n\n// DocvalueFieldWithFormat adds a single field to load from the field data cache\n// and return as part of the search.\nfunc (s *SearchService) DocvalueFieldWithFormat(docvalueField DocvalueField) *SearchService {\n\ts.searchSource = s.searchSource.DocvalueFieldWithFormat(docvalueField)\n\treturn s\n}\n\n// DocvalueFields adds one or more fields to load from the field data cache\n// and return as part of the search.\nfunc (s *SearchService) DocvalueFields(docvalueFields ...string) *SearchService {\n\ts.searchSource = s.searchSource.DocvalueFields(docvalueFields...)\n\treturn s\n}\n\n// DocvalueFieldsWithFormat adds one or more fields to load from the field data cache\n// and return as part of the search.\nfunc (s *SearchService) DocvalueFieldsWithFormat(docvalueFields ...DocvalueField) *SearchService {\n\ts.searchSource = s.searchSource.DocvalueFieldsWithFormat(docvalueFields...)\n\treturn s\n}\n\n// NoStoredFields indicates that no stored fields should be loaded, resulting in only\n// id and type to be returned per field.\nfunc (s *SearchService) NoStoredFields() *SearchService {\n\ts.searchSource = s.searchSource.NoStoredFields()\n\treturn s\n}\n\n// StoredField adds a single field to load and return (note, must be stored) as\n// part of the search request. If none are specified, the source of the\n// document will be returned.\nfunc (s *SearchService) StoredField(fieldName string) *SearchService {\n\ts.searchSource = s.searchSource.StoredField(fieldName)\n\treturn s\n}\n\n// StoredFields\tsets the fields to load and return as part of the search request.\n// If none are specified, the source of the document will be returned.\nfunc (s *SearchService) StoredFields(fields ...string) *SearchService {\n\ts.searchSource = s.searchSource.StoredFields(fields...)\n\treturn s\n}\n\n// TrackScores is applied when sorting and controls if scores will be\n// tracked as well. Defaults to false.\nfunc (s *SearchService) TrackScores(trackScores bool) *SearchService {\n\ts.searchSource = s.searchSource.TrackScores(trackScores)\n\treturn s\n}\n\n// TrackTotalHits controls if the total hit count for the query should be tracked.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.1/search-request-track-total-hits.html\n// for details.\nfunc (s *SearchService) TrackTotalHits(trackTotalHits interface{}) *SearchService {\n\ts.searchSource = s.searchSource.TrackTotalHits(trackTotalHits)\n\treturn s\n}\n\n// SearchAfter allows a different form of pagination by using a live cursor,\n// using the results of the previous page to help the retrieval of the next.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-search-after.html\nfunc (s *SearchService) SearchAfter(sortValues ...interface{}) *SearchService {\n\ts.searchSource = s.searchSource.SearchAfter(sortValues...)\n\treturn s\n}\n\n// DefaultRescoreWindowSize sets the rescore window size for rescores\n// that don't specify their window.\nfunc (s *SearchService) DefaultRescoreWindowSize(defaultRescoreWindowSize int) *SearchService {\n\ts.searchSource = s.searchSource.DefaultRescoreWindowSize(defaultRescoreWindowSize)\n\treturn s\n}\n\n// Rescorer adds a rescorer to the search.\nfunc (s *SearchService) Rescorer(rescore *Rescore) *SearchService {\n\ts.searchSource = s.searchSource.Rescorer(rescore)\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether the specified concrete indices\n// should be ignored when unavailable (missing or closed).\nfunc (s *SearchService) IgnoreUnavailable(ignoreUnavailable bool) *SearchService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// IgnoreThrottled indicates whether specified concrete, expanded or aliased\n// indices should be ignored when throttled.\nfunc (s *SearchService) IgnoreThrottled(ignoreThrottled bool) *SearchService {\n\ts.ignoreThrottled = &ignoreThrottled\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes `_all` string\n// or when no indices have been specified).\nfunc (s *SearchService) AllowNoIndices(allowNoIndices bool) *SearchService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *SearchService) ExpandWildcards(expandWildcards string) *SearchService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// Lenient specifies whether format-based query failures (such as providing\n// text to a numeric field) should be ignored.\nfunc (s *SearchService) Lenient(lenient bool) *SearchService {\n\ts.lenient = &lenient\n\treturn s\n}\n\n// MaxResponseSize sets an upper limit on the response body size that we accept,\n// to guard against OOM situations.\nfunc (s *SearchService) MaxResponseSize(maxResponseSize int64) *SearchService {\n\ts.maxResponseSize = maxResponseSize\n\treturn s\n}\n\n// AllowPartialSearchResults indicates if an error should be returned if\n// there is a partial search failure or timeout.\nfunc (s *SearchService) AllowPartialSearchResults(enabled bool) *SearchService {\n\ts.allowPartialSearchResults = &enabled\n\treturn s\n}\n\n// TypedKeys specifies whether aggregation and suggester names should be\n// prefixed by their respective types in the response.\nfunc (s *SearchService) TypedKeys(enabled bool) *SearchService {\n\ts.typedKeys = &enabled\n\treturn s\n}\n\n// SeqNoPrimaryTerm is an alias for SeqNoAndPrimaryTerm.\n//\n// Deprecated: Use SeqNoAndPrimaryTerm.\nfunc (s *SearchService) SeqNoPrimaryTerm(enabled bool) *SearchService {\n\treturn s.SeqNoAndPrimaryTerm(enabled)\n}\n\n// SeqNoAndPrimaryTerm specifies whether to return sequence number and\n// primary term of the last modification of each hit.\nfunc (s *SearchService) SeqNoAndPrimaryTerm(enabled bool) *SearchService {\n\ts.seqNoPrimaryTerm = &enabled\n\treturn s\n}\n\n// BatchedReduceSize specifies the number of shard results that should be reduced\n// at once on the coordinating node. This value should be used as a protection\n// mechanism to reduce the memory overhead per search request if the potential\n// number of shards in the request can be large.\nfunc (s *SearchService) BatchedReduceSize(size int) *SearchService {\n\ts.batchedReduceSize = &size\n\treturn s\n}\n\n// MaxConcurrentShardRequests specifies the number of concurrent shard requests\n// this search executes concurrently. This value should be used to limit the\n// impact of the search on the cluster in order to limit the number of\n// concurrent shard requests.\nfunc (s *SearchService) MaxConcurrentShardRequests(max int) *SearchService {\n\ts.maxConcurrentShardRequests = &max\n\treturn s\n}\n\n// PreFilterShardSize specifies a threshold that enforces a pre-filter roundtrip\n// to prefilter search shards based on query rewriting if the number of shards\n// the search request expands to exceeds the threshold. This filter roundtrip\n// can limit the number of shards significantly if for instance a shard can\n// not match any documents based on it's rewrite method i.e. if date filters are\n// mandatory to match but the shard bounds and the query are disjoint.\nfunc (s *SearchService) PreFilterShardSize(threshold int) *SearchService {\n\ts.preFilterShardSize = &threshold\n\treturn s\n}\n\n// RestTotalHitsAsInt indicates whether hits.total should be rendered as an\n// integer or an object in the rest search response.\nfunc (s *SearchService) RestTotalHitsAsInt(enabled bool) *SearchService {\n\ts.restTotalHitsAsInt = &enabled\n\treturn s\n}\n\n// CCSMinimizeRoundtrips indicates whether network round-trips should be minimized\n// as part of cross-cluster search requests execution.\nfunc (s *SearchService) CCSMinimizeRoundtrips(enabled bool) *SearchService {\n\ts.ccsMinimizeRoundtrips = &enabled\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SearchService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\tif len(s.index) > 0 && len(s.typ) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/_search\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t\t\"type\":  strings.Join(s.typ, \",\"),\n\t\t})\n\t} else if len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_search\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else if len(s.typ) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_all/{type}/_search\", map[string]string{\n\t\t\t\"type\": strings.Join(s.typ, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_search\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.searchType != \"\" {\n\t\tparams.Set(\"search_type\", s.searchType)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif v := s.requestCache; v != nil {\n\t\tparams.Set(\"request_cache\", fmt.Sprint(*v))\n\t}\n\tif v := s.allowNoIndices; v != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprint(*v))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif v := s.lenient; v != nil {\n\t\tparams.Set(\"lenient\", fmt.Sprint(*v))\n\t}\n\tif v := s.ignoreUnavailable; v != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*v))\n\t}\n\tif v := s.ignoreThrottled; v != nil {\n\t\tparams.Set(\"ignore_throttled\", fmt.Sprint(*v))\n\t}\n\tif s.seqNoPrimaryTerm != nil {\n\t\tparams.Set(\"seq_no_primary_term\", fmt.Sprint(*s.seqNoPrimaryTerm))\n\t}\n\tif v := s.allowPartialSearchResults; v != nil {\n\t\tparams.Set(\"allow_partial_search_results\", fmt.Sprint(*v))\n\t}\n\tif v := s.typedKeys; v != nil {\n\t\tparams.Set(\"typed_keys\", fmt.Sprint(*v))\n\t}\n\tif v := s.batchedReduceSize; v != nil {\n\t\tparams.Set(\"batched_reduce_size\", fmt.Sprint(*v))\n\t}\n\tif v := s.maxConcurrentShardRequests; v != nil {\n\t\tparams.Set(\"max_concurrent_shard_requests\", fmt.Sprint(*v))\n\t}\n\tif v := s.preFilterShardSize; v != nil {\n\t\tparams.Set(\"pre_filter_shard_size\", fmt.Sprint(*v))\n\t}\n\tif v := s.restTotalHitsAsInt; v != nil {\n\t\tparams.Set(\"rest_total_hits_as_int\", fmt.Sprint(*v))\n\t}\n\tif v := s.ccsMinimizeRoundtrips; v != nil {\n\t\tparams.Set(\"ccs_minimize_roundtrips\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SearchService) Validate() error {\n\treturn nil\n}\n\n// Do executes the search and returns a SearchResult.\nfunc (s *SearchService) Do(ctx context.Context) (*SearchResult, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Perform request\n\tvar body interface{}\n\tif s.source != nil {\n\t\tbody = s.source\n\t} else {\n\t\tsrc, err := s.searchSource.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbody = src\n\t}\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:          \"POST\",\n\t\tPath:            path,\n\t\tParams:          params,\n\t\tBody:            body,\n\t\tHeaders:         s.headers,\n\t\tMaxResponseSize: s.maxResponseSize,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return search results\n\tret := new(SearchResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\tret.Header = res.Header\n\t\treturn nil, err\n\t}\n\tret.Header = res.Header\n\treturn ret, nil\n}\n\n// SearchResult is the result of a search in Elasticsearch.\ntype SearchResult struct {\n\tHeader          http.Header          `json:\"-\"`\n\tTookInMillis    int64                `json:\"took,omitempty\"`             // search time in milliseconds\n\tTerminatedEarly bool                 `json:\"terminated_early,omitempty\"` // request terminated early\n\tNumReducePhases int                  `json:\"num_reduce_phases,omitempty\"`\n\tClusters        *SearchResultCluster `json:\"_clusters,omitempty\"`    // 6.1.0+\n\tScrollId        string               `json:\"_scroll_id,omitempty\"`   // only used with Scroll and Scan operations\n\tHits            *SearchHits          `json:\"hits,omitempty\"`         // the actual search hits\n\tSuggest         SearchSuggest        `json:\"suggest,omitempty\"`      // results from suggesters\n\tAggregations    Aggregations         `json:\"aggregations,omitempty\"` // results from aggregations\n\tTimedOut        bool                 `json:\"timed_out,omitempty\"`    // true if the search timed out\n\tError           *ErrorDetails        `json:\"error,omitempty\"`        // only used in MultiGet\n\tProfile         *SearchProfile       `json:\"profile,omitempty\"`      // profiling results, if optional Profile API was active for this search\n\tShards          *ShardsInfo          `json:\"_shards,omitempty\"`      // shard information\n\tStatus          int                  `json:\"status,omitempty\"`       // used in MultiSearch\n\tPitId           string               `json:\"pit_id,omitempty\"`       // Point In Time ID\n}\n\n// SearchResultCluster holds information about a search response\n// from a cluster.\ntype SearchResultCluster struct {\n\tSuccessful int `json:\"successful,omitempty\"`\n\tTotal      int `json:\"total,omitempty\"`\n\tSkipped    int `json:\"skipped,omitempty\"`\n}\n\n// TotalHits is a convenience function to return the number of hits for\n// a search result. The return value might not be accurate, unless\n// track_total_hits parameter has set to true.\nfunc (r *SearchResult) TotalHits() int64 {\n\tif r != nil && r.Hits != nil && r.Hits.TotalHits != nil {\n\t\treturn r.Hits.TotalHits.Value\n\t}\n\treturn 0\n}\n\n// Each is a utility function to iterate over all hits. It saves you from\n// checking for nil values. Notice that Each will ignore errors in\n// serializing JSON and hits with empty/nil _source will get an empty\n// value\nfunc (r *SearchResult) Each(typ reflect.Type) []interface{} {\n\tif r.Hits == nil || r.Hits.Hits == nil || len(r.Hits.Hits) == 0 {\n\t\treturn nil\n\t}\n\tslice := make([]interface{}, 0, len(r.Hits.Hits))\n\tfor _, hit := range r.Hits.Hits {\n\t\tv := reflect.New(typ).Elem()\n\t\tif hit.Source == nil {\n\t\t\tslice = append(slice, v.Interface())\n\t\t\tcontinue\n\t\t}\n\t\tif err := json.Unmarshal(hit.Source, v.Addr().Interface()); err == nil {\n\t\t\tslice = append(slice, v.Interface())\n\t\t}\n\t}\n\treturn slice\n}\n\n// SearchHits specifies the list of search hits.\ntype SearchHits struct {\n\tTotalHits *TotalHits   `json:\"total,omitempty\"`     // total number of hits found\n\tMaxScore  *float64     `json:\"max_score,omitempty\"` // maximum score of all hits\n\tHits      []*SearchHit `json:\"hits,omitempty\"`      // the actual hits returned\n}\n\n// NestedHit is a nested innerhit\ntype NestedHit struct {\n\tField  string     `json:\"field\"`\n\tOffset int        `json:\"offset,omitempty\"`\n\tChild  *NestedHit `json:\"_nested,omitempty\"`\n}\n\n// TotalHits specifies total number of hits and its relation\ntype TotalHits struct {\n\tValue    int64  `json:\"value\"`    // value of the total hit count\n\tRelation string `json:\"relation\"` // how the value should be interpreted: accurate (\"eq\") or a lower bound (\"gte\")\n}\n\n// UnmarshalJSON into TotalHits, accepting both the new response structure\n// in ES 7.x as well as the older response structure in earlier versions.\n// The latter can be enabled with RestTotalHitsAsInt(true).\nfunc (h *TotalHits) UnmarshalJSON(data []byte) error {\n\tif data == nil || string(data) == \"null\" {\n\t\treturn nil\n\t}\n\tvar v struct {\n\t\tValue    int64  `json:\"value\"`    // value of the total hit count\n\t\tRelation string `json:\"relation\"` // how the value should be interpreted: accurate (\"eq\") or a lower bound (\"gte\")\n\t}\n\tif err := json.Unmarshal(data, &v); err != nil {\n\t\tvar count int64\n\t\tif err2 := json.Unmarshal(data, &count); err2 != nil {\n\t\t\treturn err // return inner error\n\t\t}\n\t\th.Value = count\n\t\th.Relation = \"eq\"\n\t\treturn nil\n\t}\n\t*h = v\n\treturn nil\n}\n\n// SearchHit is a single hit.\ntype SearchHit struct {\n\tScore          *float64                       `json:\"_score,omitempty\"`   // computed score\n\tIndex          string                         `json:\"_index,omitempty\"`   // index name\n\tType           string                         `json:\"_type,omitempty\"`    // type meta field\n\tId             string                         `json:\"_id,omitempty\"`      // external or internal\n\tUid            string                         `json:\"_uid,omitempty\"`     // uid meta field (see MapperService.java for all meta fields)\n\tRouting        string                         `json:\"_routing,omitempty\"` // routing meta field\n\tParent         string                         `json:\"_parent,omitempty\"`  // parent meta field\n\tVersion        *int64                         `json:\"_version,omitempty\"` // version number, when Version is set to true in SearchService\n\tSeqNo          *int64                         `json:\"_seq_no\"`\n\tPrimaryTerm    *int64                         `json:\"_primary_term\"`\n\tSort           []interface{}                  `json:\"sort,omitempty\"`            // sort information\n\tHighlight      SearchHitHighlight             `json:\"highlight,omitempty\"`       // highlighter information\n\tSource         json.RawMessage                `json:\"_source,omitempty\"`         // stored document source\n\tFields         SearchHitFields                `json:\"fields,omitempty\"`          // returned (stored) fields\n\tExplanation    *SearchExplanation             `json:\"_explanation,omitempty\"`    // explains how the score was computed\n\tMatchedQueries []string                       `json:\"matched_queries,omitempty\"` // matched queries\n\tInnerHits      map[string]*SearchHitInnerHits `json:\"inner_hits,omitempty\"`      // inner hits with ES >= 1.5.0\n\tNested         *NestedHit                     `json:\"_nested,omitempty\"`         // for nested inner hits\n\tShard          string                         `json:\"_shard,omitempty\"`          // used e.g. in Search Explain\n\tNode           string                         `json:\"_node,omitempty\"`           // used e.g. in Search Explain\n\n\t// HighlightFields\n\t// SortValues\n\t// MatchedFilters\n}\n\n// SearchHitFields helps to simplify resolving slices of specific types.\ntype SearchHitFields map[string]interface{}\n\n// Strings returns a slice of strings for the given field, if there is any\n// such field in the hit. The method ignores elements that are not of type\n// string.\nfunc (f SearchHitFields) Strings(fieldName string) ([]string, bool) {\n\tslice, ok := f[fieldName].([]interface{})\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tresults := make([]string, 0, len(slice))\n\tfor _, item := range slice {\n\t\tif v, ok := item.(string); ok {\n\t\t\tresults = append(results, v)\n\t\t}\n\t}\n\treturn results, true\n}\n\n// Float64s returns a slice of float64's for the given field, if there is any\n// such field in the hit. The method ignores elements that are not of\n// type float64.\nfunc (f SearchHitFields) Float64s(fieldName string) ([]float64, bool) {\n\tslice, ok := f[fieldName].([]interface{})\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tresults := make([]float64, 0, len(slice))\n\tfor _, item := range slice {\n\t\tif v, ok := item.(float64); ok {\n\t\t\tresults = append(results, v)\n\t\t}\n\t}\n\treturn results, true\n}\n\n// SearchHitInnerHits is used for inner hits.\ntype SearchHitInnerHits struct {\n\tHits *SearchHits `json:\"hits,omitempty\"`\n}\n\n// SearchExplanation explains how the score for a hit was computed.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-explain.html.\ntype SearchExplanation struct {\n\tValue       float64             `json:\"value\"`             // e.g. 1.0\n\tDescription string              `json:\"description\"`       // e.g. \"boost\" or \"ConstantScore(*:*), product of:\"\n\tDetails     []SearchExplanation `json:\"details,omitempty\"` // recursive details\n}\n\n// Suggest\n\n// SearchSuggest is a map of suggestions.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters.html.\ntype SearchSuggest map[string][]SearchSuggestion\n\n// SearchSuggestion is a single search suggestion.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters.html.\ntype SearchSuggestion struct {\n\tText    string                   `json:\"text\"`\n\tOffset  int                      `json:\"offset\"`\n\tLength  int                      `json:\"length\"`\n\tOptions []SearchSuggestionOption `json:\"options\"`\n}\n\n// SearchSuggestionOption is an option of a SearchSuggestion.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters.html.\ntype SearchSuggestionOption struct {\n\tText            string              `json:\"text\"`\n\tIndex           string              `json:\"_index\"`\n\tType            string              `json:\"_type\"`\n\tId              string              `json:\"_id\"`\n\tScore           float64             `json:\"score\"`  // term and phrase suggesters uses \"score\" as of 6.2.4\n\tScoreUnderscore float64             `json:\"_score\"` // completion and context suggesters uses \"_score\" as of 6.2.4\n\tHighlighted     string              `json:\"highlighted\"`\n\tCollateMatch    bool                `json:\"collate_match\"`\n\tFreq            int                 `json:\"freq\"` // from TermSuggestion.Option in Java API\n\tSource          json.RawMessage     `json:\"_source\"`\n\tContexts        map[string][]string `json:\"contexts,omitempty\"`\n}\n\n// SearchProfile is a list of shard profiling data collected during\n// query execution in the \"profile\" section of a SearchResult\ntype SearchProfile struct {\n\tShards []SearchProfileShardResult `json:\"shards\"`\n}\n\n// SearchProfileShardResult returns the profiling data for a single shard\n// accessed during the search query or aggregation.\ntype SearchProfileShardResult struct {\n\tID           string                    `json:\"id\"`\n\tSearches     []QueryProfileShardResult `json:\"searches\"`\n\tAggregations []ProfileResult           `json:\"aggregations\"`\n\tFetch        *ProfileResult            `json:\"fetch\"`\n}\n\n// QueryProfileShardResult is a container class to hold the profile results\n// for a single shard in the request. It comtains a list of query profiles,\n// a collector tree and a total rewrite tree.\ntype QueryProfileShardResult struct {\n\tQuery       []ProfileResult `json:\"query,omitempty\"`\n\tRewriteTime int64           `json:\"rewrite_time,omitempty\"`\n\tCollector   []interface{}   `json:\"collector,omitempty\"`\n}\n\n// CollectorResult holds the profile timings of the collectors used in the\n// search. Children's CollectorResults may be embedded inside of a parent\n// CollectorResult.\ntype CollectorResult struct {\n\tName      string            `json:\"name,omitempty\"`\n\tReason    string            `json:\"reason,omitempty\"`\n\tTime      string            `json:\"time,omitempty\"`\n\tTimeNanos int64             `json:\"time_in_nanos,omitempty\"`\n\tChildren  []CollectorResult `json:\"children,omitempty\"`\n}\n\n// ProfileResult is the internal representation of a profiled query,\n// corresponding to a single node in the query tree.\ntype ProfileResult struct {\n\tType          string                 `json:\"type\"`\n\tDescription   string                 `json:\"description,omitempty\"`\n\tNodeTime      string                 `json:\"time,omitempty\"`\n\tNodeTimeNanos int64                  `json:\"time_in_nanos,omitempty\"`\n\tBreakdown     map[string]int64       `json:\"breakdown,omitempty\"`\n\tChildren      []ProfileResult        `json:\"children,omitempty\"`\n\tDebug         map[string]interface{} `json:\"debug,omitempty\"`\n}\n\n// Aggregations (see search_aggs.go)\n\n// Highlighting\n\n// SearchHitHighlight is the highlight information of a search hit.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-highlighting.html\n// for a general discussion of highlighting.\ntype SearchHitHighlight map[string][]string\n"
  },
  {
    "path": "search_aggs.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n)\n\n// Aggregations can be seen as a unit-of-work that build\n// analytic information over a set of documents. It is\n// (in many senses) the follow-up of facets in Elasticsearch.\n// For more details about aggregations, visit:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations.html\ntype Aggregation interface {\n\t// Source returns a JSON-serializable aggregation that is a fragment\n\t// of the request sent to Elasticsearch.\n\tSource() (interface{}, error)\n}\n\n// Aggregations is a list of aggregations that are part of a search result.\ntype Aggregations map[string]json.RawMessage\n\n// Min returns min aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-min-aggregation.html\nfunc (a Aggregations) Min(name string) (*AggregationValueMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationValueMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Max returns max aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-max-aggregation.html\nfunc (a Aggregations) Max(name string) (*AggregationValueMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationValueMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Sum returns sum aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-sum-aggregation.html\nfunc (a Aggregations) Sum(name string) (*AggregationValueMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationValueMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Avg returns average aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-avg-aggregation.html\nfunc (a Aggregations) Avg(name string) (*AggregationValueMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationValueMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// WeightedAvg computes the weighted average of numeric values that are extracted from the aggregated documents.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-weight-avg-aggregation.html\nfunc (a Aggregations) WeightedAvg(name string) (*AggregationValueMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationValueMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// MedianAbsoluteDeviation returns median absolute deviation aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.6/search-aggregations-metrics-median-absolute-deviation-aggregation.html\n// for details.\nfunc (a Aggregations) MedianAbsoluteDeviation(name string) (*AggregationValueMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationValueMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// ValueCount returns value-count aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-valuecount-aggregation.html\nfunc (a Aggregations) ValueCount(name string) (*AggregationValueMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationValueMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Cardinality returns cardinality aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-cardinality-aggregation.html\nfunc (a Aggregations) Cardinality(name string) (*AggregationValueMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationValueMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Stats returns stats aggregation results.\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-stats-aggregation.html\nfunc (a Aggregations) Stats(name string) (*AggregationStatsMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationStatsMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// ExtendedStats returns extended stats aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-extendedstats-aggregation.html\nfunc (a Aggregations) ExtendedStats(name string) (*AggregationExtendedStatsMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationExtendedStatsMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// MatrixStats returns matrix stats aggregation results.\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-matrix-stats-aggregation.html\nfunc (a Aggregations) MatrixStats(name string) (*AggregationMatrixStats, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationMatrixStats)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Percentiles returns percentiles results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-percentile-aggregation.html\nfunc (a Aggregations) Percentiles(name string) (*AggregationPercentilesMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPercentilesMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// PercentileRanks returns percentile ranks results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-percentile-rank-aggregation.html\nfunc (a Aggregations) PercentileRanks(name string) (*AggregationPercentilesMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPercentilesMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// TopHits returns top-hits aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-top-hits-aggregation.html\nfunc (a Aggregations) TopHits(name string) (*AggregationTopHitsMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationTopHitsMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Global returns global results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-global-aggregation.html\nfunc (a Aggregations) Global(name string) (*AggregationSingleBucket, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationSingleBucket)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Filter returns filter results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-filter-aggregation.html\nfunc (a Aggregations) Filter(name string) (*AggregationSingleBucket, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationSingleBucket)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Filters returns filters results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-filters-aggregation.html\nfunc (a Aggregations) Filters(name string) (*AggregationBucketFilters, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketFilters)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// AdjacencyMatrix returning a form of adjacency matrix.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-adjacency-matrix-aggregation.html\nfunc (a Aggregations) AdjacencyMatrix(name string) (*AggregationBucketAdjacencyMatrix, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketAdjacencyMatrix)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Missing returns missing results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-missing-aggregation.html\nfunc (a Aggregations) Missing(name string) (*AggregationSingleBucket, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationSingleBucket)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Nested returns nested results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-nested-aggregation.html\nfunc (a Aggregations) Nested(name string) (*AggregationSingleBucket, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationSingleBucket)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// ReverseNested returns reverse-nested results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-reverse-nested-aggregation.html\nfunc (a Aggregations) ReverseNested(name string) (*AggregationSingleBucket, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationSingleBucket)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Children returns children results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-children-aggregation.html\nfunc (a Aggregations) Children(name string) (*AggregationSingleBucket, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationSingleBucket)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Terms returns terms aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-terms-aggregation.html\nfunc (a Aggregations) Terms(name string) (*AggregationBucketKeyItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketKeyItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// MultiTerms returns multi terms aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-bucket-multi-terms-aggregation.html\nfunc (a Aggregations) MultiTerms(name string) (*AggregationBucketMultiKeyItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketMultiKeyItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// SignificantTerms returns significant terms aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html\nfunc (a Aggregations) SignificantTerms(name string) (*AggregationBucketSignificantTerms, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketSignificantTerms)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// RareTerms returns rate terms aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-rare-terms-aggregation.html\nfunc (a Aggregations) RareTerms(name string) (*AggregationBucketKeyItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketKeyItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Sampler returns sampler aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-sampler-aggregation.html\nfunc (a Aggregations) Sampler(name string) (*AggregationSingleBucket, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationSingleBucket)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// DiversifiedSampler returns diversified_sampler aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-diversified-sampler-aggregation.html\nfunc (a Aggregations) DiversifiedSampler(name string) (*AggregationSingleBucket, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationSingleBucket)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Range returns range aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-range-aggregation.html\nfunc (a Aggregations) Range(name string) (*AggregationBucketRangeItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketRangeItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// KeyedRange returns keyed range aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-range-aggregation.html.\nfunc (a Aggregations) KeyedRange(name string) (*AggregationBucketKeyedRangeItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketKeyedRangeItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// DateRange returns date range aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-daterange-aggregation.html\nfunc (a Aggregations) DateRange(name string) (*AggregationBucketRangeItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketRangeItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// IPRange returns IP range aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-iprange-aggregation.html\nfunc (a Aggregations) IPRange(name string) (*AggregationBucketRangeItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketRangeItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Histogram returns histogram aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-histogram-aggregation.html\nfunc (a Aggregations) Histogram(name string) (*AggregationBucketHistogramItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketHistogramItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// AutoDateHistogram returns auto date histogram aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-datehistogram-aggregation.html\nfunc (a Aggregations) AutoDateHistogram(name string) (*AggregationBucketHistogramItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketHistogramItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// DateHistogram returns date histogram aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-datehistogram-aggregation.html\nfunc (a Aggregations) DateHistogram(name string) (*AggregationBucketHistogramItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketHistogramItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// KeyedDateHistogram returns date histogram aggregation results for keyed responses.\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-datehistogram-aggregation.html#_keyed_response_3\nfunc (a Aggregations) KeyedDateHistogram(name string) (*AggregationBucketKeyedHistogramItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketKeyedHistogramItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// GeoBounds returns geo-bounds aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-geobounds-aggregation.html\nfunc (a Aggregations) GeoBounds(name string) (*AggregationGeoBoundsMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationGeoBoundsMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// GeoHash returns geo-hash aggregation results.\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-geohashgrid-aggregation.html\nfunc (a Aggregations) GeoHash(name string) (*AggregationBucketKeyItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketKeyItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// GeoTile returns geo-tile aggregation results.\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-geotilegrid-aggregation.html\nfunc (a Aggregations) GeoTile(name string) (*AggregationBucketKeyItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketKeyItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// GeoCentroid returns geo-centroid aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-geocentroid-aggregation.html\nfunc (a Aggregations) GeoCentroid(name string) (*AggregationGeoCentroidMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationGeoCentroidMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// GeoDistance returns geo distance aggregation results.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-geodistance-aggregation.html\nfunc (a Aggregations) GeoDistance(name string) (*AggregationBucketRangeItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketRangeItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// AvgBucket returns average bucket pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-avg-bucket-aggregation.html\nfunc (a Aggregations) AvgBucket(name string) (*AggregationPipelineSimpleValue, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineSimpleValue)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// SumBucket returns sum bucket pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-sum-bucket-aggregation.html\nfunc (a Aggregations) SumBucket(name string) (*AggregationPipelineSimpleValue, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineSimpleValue)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// StatsBucket returns stats bucket pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-stats-bucket-aggregation.html\nfunc (a Aggregations) StatsBucket(name string) (*AggregationPipelineStatsMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineStatsMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// PercentilesBucket returns stats bucket pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-percentiles-bucket-aggregation.html\nfunc (a Aggregations) PercentilesBucket(name string) (*AggregationPipelinePercentilesMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelinePercentilesMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// MaxBucket returns maximum bucket pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-max-bucket-aggregation.html\nfunc (a Aggregations) MaxBucket(name string) (*AggregationPipelineBucketMetricValue, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineBucketMetricValue)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// MinBucket returns minimum bucket pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-min-bucket-aggregation.html\nfunc (a Aggregations) MinBucket(name string) (*AggregationPipelineBucketMetricValue, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineBucketMetricValue)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// MovAvg returns moving average pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movavg-aggregation.html\n//\n// Deprecated: The MovAvgAggregation has been deprecated in 6.4.0. Use the more generate MovFnAggregation instead.\nfunc (a Aggregations) MovAvg(name string) (*AggregationPipelineSimpleValue, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineSimpleValue)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// MovFn returns moving function pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movfn-aggregation.html\nfunc (a Aggregations) MovFn(name string) (*AggregationPipelineSimpleValue, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineSimpleValue)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Derivative returns derivative pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-derivative-aggregation.html\nfunc (a Aggregations) Derivative(name string) (*AggregationPipelineDerivative, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineDerivative)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// CumulativeSum returns a cumulative sum pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-cumulative-sum-aggregation.html\nfunc (a Aggregations) CumulativeSum(name string) (*AggregationPipelineSimpleValue, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineSimpleValue)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// BucketScript returns bucket script pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-bucket-script-aggregation.html\nfunc (a Aggregations) BucketScript(name string) (*AggregationPipelineSimpleValue, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineSimpleValue)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// SerialDiff returns serial differencing pipeline aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-serialdiff-aggregation.html\nfunc (a Aggregations) SerialDiff(name string) (*AggregationPipelineSimpleValue, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationPipelineSimpleValue)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// Composite returns composite bucket aggregation results.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-composite-aggregation.html\n// for details.\nfunc (a Aggregations) Composite(name string) (*AggregationBucketCompositeItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationBucketCompositeItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// ScriptedMetric returns scripted metric aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.2/search-aggregations-metrics-scripted-metric-aggregation.html\n// for details.\nfunc (a Aggregations) ScriptedMetric(name string) (*AggregationScriptedMetric, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationScriptedMetric)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// TopMetrics returns top metrics aggregation results.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-top-metrics.html\n//for details\nfunc (a Aggregations) TopMetrics(name string) (*AggregationTopMetricsItems, bool) {\n\tif raw, found := a[name]; found {\n\t\tagg := new(AggregationTopMetricsItems)\n\t\tif raw == nil {\n\t\t\treturn agg, true\n\t\t}\n\t\tif err := json.Unmarshal(raw, agg); err == nil {\n\t\t\treturn agg, true\n\t\t}\n\t}\n\treturn nil, false\n}\n\n// -- Single value metric --\n\n// AggregationValueMetric is a single-value metric, returned e.g. by a\n// Min or Max aggregation.\ntype AggregationValueMetric struct {\n\tAggregations\n\n\tValue *float64               //`json:\"value\"`\n\tMeta  map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationValueMetric structure.\nfunc (a *AggregationValueMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"value\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Value)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Stats metric --\n\n// AggregationStatsMetric is a multi-value metric, returned by a Stats aggregation.\ntype AggregationStatsMetric struct {\n\tAggregations\n\n\tCount int64                  // `json:\"count\"`\n\tMin   *float64               //`json:\"min,omitempty\"`\n\tMax   *float64               //`json:\"max,omitempty\"`\n\tAvg   *float64               //`json:\"avg,omitempty\"`\n\tSum   *float64               //`json:\"sum,omitempty\"`\n\tMeta  map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationStatsMetric structure.\nfunc (a *AggregationStatsMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Count)\n\t}\n\tif v, ok := aggs[\"min\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Min)\n\t}\n\tif v, ok := aggs[\"max\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Max)\n\t}\n\tif v, ok := aggs[\"avg\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Avg)\n\t}\n\tif v, ok := aggs[\"sum\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Sum)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Extended stats metric --\n\n// AggregationExtendedStatsMetric is a multi-value metric, returned by an ExtendedStats aggregation.\ntype AggregationExtendedStatsMetric struct {\n\tAggregations\n\n\tCount        int64                  // `json:\"count\"`\n\tMin          *float64               //`json:\"min,omitempty\"`\n\tMax          *float64               //`json:\"max,omitempty\"`\n\tAvg          *float64               //`json:\"avg,omitempty\"`\n\tSum          *float64               //`json:\"sum,omitempty\"`\n\tSumOfSquares *float64               //`json:\"sum_of_squares,omitempty\"`\n\tVariance     *float64               //`json:\"variance,omitempty\"`\n\tStdDeviation *float64               //`json:\"std_deviation,omitempty\"`\n\tMeta         map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationExtendedStatsMetric structure.\nfunc (a *AggregationExtendedStatsMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Count)\n\t}\n\tif v, ok := aggs[\"min\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Min)\n\t}\n\tif v, ok := aggs[\"max\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Max)\n\t}\n\tif v, ok := aggs[\"avg\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Avg)\n\t}\n\tif v, ok := aggs[\"sum\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Sum)\n\t}\n\tif v, ok := aggs[\"sum_of_squares\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.SumOfSquares)\n\t}\n\tif v, ok := aggs[\"variance\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Variance)\n\t}\n\tif v, ok := aggs[\"std_deviation\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.StdDeviation)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Matrix Stats --\n\n// AggregationMatrixStats is returned by a MatrixStats aggregation.\ntype AggregationMatrixStats struct {\n\tAggregations\n\n\tFields []*AggregationMatrixStatsField // `json:\"field,omitempty\"`\n\tMeta   map[string]interface{}         // `json:\"meta,omitempty\"`\n}\n\n// AggregationMatrixStatsField represents running stats of a single field\n// returned from MatrixStats aggregation.\ntype AggregationMatrixStatsField struct {\n\tName        string             `json:\"name\"`\n\tCount       int64              `json:\"count\"`\n\tMean        float64            `json:\"mean,omitempty\"`\n\tVariance    float64            `json:\"variance,omitempty\"`\n\tSkewness    float64            `json:\"skewness,omitempty\"`\n\tKurtosis    float64            `json:\"kurtosis,omitempty\"`\n\tCovariance  map[string]float64 `json:\"covariance,omitempty\"`\n\tCorrelation map[string]float64 `json:\"correlation,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationMatrixStats structure.\nfunc (a *AggregationMatrixStats) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"fields\"]; ok && v != nil {\n\t\t// RunningStats for every field\n\t\tjson.Unmarshal(v, &a.Fields)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Percentiles metric --\n\n// AggregationPercentilesMetric is a multi-value metric, returned by a Percentiles aggregation.\ntype AggregationPercentilesMetric struct {\n\tAggregations\n\n\tValues map[string]float64     // `json:\"values\"`\n\tMeta   map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationPercentilesMetric structure.\nfunc (a *AggregationPercentilesMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"values\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Values)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Top-hits metric --\n\n// AggregationTopHitsMetric is a metric returned by a TopHits aggregation.\ntype AggregationTopHitsMetric struct {\n\tAggregations\n\n\tHits *SearchHits            //`json:\"hits\"`\n\tMeta map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationTopHitsMetric structure.\nfunc (a *AggregationTopHitsMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\ta.Aggregations = aggs\n\ta.Hits = new(SearchHits)\n\tif v, ok := aggs[\"hits\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Hits)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\treturn nil\n}\n\n// -- Geo-bounds metric --\n\n// AggregationGeoBoundsMetric is a metric as returned by a GeoBounds aggregation.\ntype AggregationGeoBoundsMetric struct {\n\tAggregations\n\n\tBounds struct {\n\t\tTopLeft struct {\n\t\t\tLatitude  float64 `json:\"lat\"`\n\t\t\tLongitude float64 `json:\"lon\"`\n\t\t} `json:\"top_left\"`\n\t\tBottomRight struct {\n\t\t\tLatitude  float64 `json:\"lat\"`\n\t\t\tLongitude float64 `json:\"lon\"`\n\t\t} `json:\"bottom_right\"`\n\t} `json:\"bounds\"`\n\n\tMeta map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationGeoBoundsMetric structure.\nfunc (a *AggregationGeoBoundsMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"bounds\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Bounds)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationGeoCentroidMetric is a metric as returned by a GeoCentroid aggregation.\ntype AggregationGeoCentroidMetric struct {\n\tAggregations\n\n\tLocation struct {\n\t\tLatitude  float64 `json:\"lat\"`\n\t\tLongitude float64 `json:\"lon\"`\n\t} `json:\"location\"`\n\n\tCount int // `json:\"count,omitempty\"`\n\n\tMeta map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationGeoCentroidMetric structure.\nfunc (a *AggregationGeoCentroidMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"location\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Location)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\tif v, ok := aggs[\"count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Count)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Single bucket --\n\n// AggregationSingleBucket is a single bucket, returned e.g. via an aggregation of type Global.\ntype AggregationSingleBucket struct {\n\tAggregations\n\n\tDocCount int64                  // `json:\"doc_count\"`\n\tMeta     map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationSingleBucket structure.\nfunc (a *AggregationSingleBucket) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCount)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Bucket range items --\n\n// AggregationBucketRangeItems is a bucket aggregation that is e.g. returned\n// with a range aggregation.\ntype AggregationBucketRangeItems struct {\n\tAggregations\n\n\tDocCountErrorUpperBound int64                         //`json:\"doc_count_error_upper_bound\"`\n\tSumOfOtherDocCount      int64                         //`json:\"sum_other_doc_count\"`\n\tBuckets                 []*AggregationBucketRangeItem //`json:\"buckets\"`\n\tMeta                    map[string]interface{}        // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketRangeItems structure.\nfunc (a *AggregationBucketRangeItems) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"doc_count_error_upper_bound\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCountErrorUpperBound)\n\t}\n\tif v, ok := aggs[\"sum_other_doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.SumOfOtherDocCount)\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationBucketKeyedRangeItems is a bucket aggregation that is e.g. returned\n// with a keyed range aggregation.\ntype AggregationBucketKeyedRangeItems struct {\n\tAggregations\n\n\tDocCountErrorUpperBound int64                                  //`json:\"doc_count_error_upper_bound\"`\n\tSumOfOtherDocCount      int64                                  //`json:\"sum_other_doc_count\"`\n\tBuckets                 map[string]*AggregationBucketRangeItem //`json:\"buckets\"`\n\tMeta                    map[string]interface{}                 // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketRangeItems structure.\nfunc (a *AggregationBucketKeyedRangeItems) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"doc_count_error_upper_bound\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCountErrorUpperBound)\n\t}\n\tif v, ok := aggs[\"sum_other_doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.SumOfOtherDocCount)\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationBucketRangeItem is a single bucket of an AggregationBucketRangeItems structure.\ntype AggregationBucketRangeItem struct {\n\tAggregations\n\n\tKey          string   //`json:\"key\"`\n\tDocCount     int64    //`json:\"doc_count\"`\n\tFrom         *float64 //`json:\"from\"`\n\tFromAsString string   //`json:\"from_as_string\"`\n\tTo           *float64 //`json:\"to\"`\n\tToAsString   string   //`json:\"to_as_string\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketRangeItem structure.\nfunc (a *AggregationBucketRangeItem) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"key\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Key)\n\t}\n\tif v, ok := aggs[\"doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCount)\n\t}\n\tif v, ok := aggs[\"from\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.From)\n\t}\n\tif v, ok := aggs[\"from_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.FromAsString)\n\t}\n\tif v, ok := aggs[\"to\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.To)\n\t}\n\tif v, ok := aggs[\"to_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.ToAsString)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Bucket key items --\n\n// AggregationBucketKeyItems is a bucket aggregation that is e.g. returned\n// with a terms aggregation.\ntype AggregationBucketKeyItems struct {\n\tAggregations\n\n\tDocCountErrorUpperBound int64                       //`json:\"doc_count_error_upper_bound\"`\n\tSumOfOtherDocCount      int64                       //`json:\"sum_other_doc_count\"`\n\tBuckets                 []*AggregationBucketKeyItem //`json:\"buckets\"`\n\tMeta                    map[string]interface{}      // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketKeyItems structure.\nfunc (a *AggregationBucketKeyItems) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"doc_count_error_upper_bound\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCountErrorUpperBound)\n\t}\n\tif v, ok := aggs[\"sum_other_doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.SumOfOtherDocCount)\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationBucketKeyItem is a single bucket of an AggregationBucketKeyItems structure.\ntype AggregationBucketKeyItem struct {\n\tAggregations\n\n\tKey         interface{} //`json:\"key\"`\n\tKeyAsString *string     //`json:\"key_as_string\"`\n\tKeyNumber   json.Number\n\tDocCount    int64 //`json:\"doc_count\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketKeyItem structure.\nfunc (a *AggregationBucketKeyItem) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tdec := json.NewDecoder(bytes.NewReader(data))\n\tdec.UseNumber()\n\tif err := dec.Decode(&aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"key\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Key)\n\t\tjson.Unmarshal(v, &a.KeyNumber)\n\t}\n\tif v, ok := aggs[\"key_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.KeyAsString)\n\t}\n\tif v, ok := aggs[\"doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCount)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationBucketMultiKeyItems is a bucket aggregation that is returned\n// with a multi terms aggregation.\ntype AggregationBucketMultiKeyItems struct {\n\tAggregations\n\n\tDocCountErrorUpperBound int64                            //`json:\"doc_count_error_upper_bound\"`\n\tSumOfOtherDocCount      int64                            //`json:\"sum_other_doc_count\"`\n\tBuckets                 []*AggregationBucketMultiKeyItem //`json:\"buckets\"`\n\tMeta                    map[string]interface{}           // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketMultiKeyItems structure.\nfunc (a *AggregationBucketMultiKeyItems) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"doc_count_error_upper_bound\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCountErrorUpperBound)\n\t}\n\tif v, ok := aggs[\"sum_other_doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.SumOfOtherDocCount)\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationBucketMultiKeyItem is a single bucket of an AggregationBucketMultiKeyItems structure.\ntype AggregationBucketMultiKeyItem struct {\n\tAggregations\n\n\tKey         []interface{} //`json:\"key\"`\n\tKeyAsString *string       //`json:\"key_as_string\"`\n\tKeyNumber   []json.Number\n\tDocCount    int64 //`json:\"doc_count\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketMultiKeyItem structure.\nfunc (a *AggregationBucketMultiKeyItem) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tdec := json.NewDecoder(bytes.NewReader(data))\n\tdec.UseNumber()\n\tif err := dec.Decode(&aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"key\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Key)\n\t\tjson.Unmarshal(v, &a.KeyNumber)\n\t}\n\tif v, ok := aggs[\"key_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.KeyAsString)\n\t}\n\tif v, ok := aggs[\"doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCount)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Bucket types for significant terms --\n\n// AggregationBucketSignificantTerms is a bucket aggregation returned\n// with a significant terms aggregation.\ntype AggregationBucketSignificantTerms struct {\n\tAggregations\n\n\tDocCount int64                               //`json:\"doc_count\"`\n\tBuckets  []*AggregationBucketSignificantTerm //`json:\"buckets\"`\n\tMeta     map[string]interface{}              // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketSignificantTerms structure.\nfunc (a *AggregationBucketSignificantTerms) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCount)\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationBucketSignificantTerm is a single bucket of an AggregationBucketSignificantTerms structure.\ntype AggregationBucketSignificantTerm struct {\n\tAggregations\n\n\tKey      string  //`json:\"key\"`\n\tDocCount int64   //`json:\"doc_count\"`\n\tBgCount  int64   //`json:\"bg_count\"`\n\tScore    float64 //`json:\"score\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketSignificantTerm structure.\nfunc (a *AggregationBucketSignificantTerm) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"key\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Key)\n\t}\n\tif v, ok := aggs[\"doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCount)\n\t}\n\tif v, ok := aggs[\"bg_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.BgCount)\n\t}\n\tif v, ok := aggs[\"score\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Score)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Bucket filters --\n\n// AggregationBucketFilters is a multi-bucket aggregation that is returned\n// with a filters aggregation.\ntype AggregationBucketFilters struct {\n\tAggregations\n\n\tBuckets      []*AggregationBucketKeyItem          //`json:\"buckets\"`\n\tNamedBuckets map[string]*AggregationBucketKeyItem //`json:\"buckets\"`\n\tMeta         map[string]interface{}               // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketFilters structure.\nfunc (a *AggregationBucketFilters) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t\tjson.Unmarshal(v, &a.NamedBuckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Bucket AdjacencyMatrix --\n\n// AggregationBucketAdjacencyMatrix is a multi-bucket aggregation that is returned\n// with a AdjacencyMatrix aggregation.\ntype AggregationBucketAdjacencyMatrix struct {\n\tAggregations\n\n\tBuckets []*AggregationBucketKeyItem //`json:\"buckets\"`\n\tMeta    map[string]interface{}      // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketAdjacencyMatrix structure.\nfunc (a *AggregationBucketAdjacencyMatrix) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Bucket histogram items --\n\n// AggregationBucketHistogramItems is a bucket aggregation that is returned\n// with a date histogram aggregation.\ntype AggregationBucketHistogramItems struct {\n\tAggregations\n\n\tBuckets []*AggregationBucketHistogramItem // `json:\"buckets\"`\n\tMeta    map[string]interface{}            // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketHistogramItems structure.\nfunc (a *AggregationBucketHistogramItems) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationBucketKeyedHistogramItems is a bucket aggregation that is returned\n// with a (keyed) date histogram aggregation.\ntype AggregationBucketKeyedHistogramItems struct {\n\tAggregations\n\n\tBuckets map[string]*AggregationBucketHistogramItem //`json:\"buckets\"`\n\tMeta    map[string]interface{}                     // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketKeyedHistogramItems structure.\nfunc (a *AggregationBucketKeyedHistogramItems) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationBucketHistogramItem is a single bucket of an AggregationBucketHistogramItems structure.\ntype AggregationBucketHistogramItem struct {\n\tAggregations\n\n\tKey         float64 //`json:\"key\"`\n\tKeyAsString *string //`json:\"key_as_string\"`\n\tDocCount    int64   //`json:\"doc_count\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketHistogramItem structure.\nfunc (a *AggregationBucketHistogramItem) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"key\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Key)\n\t}\n\tif v, ok := aggs[\"key_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.KeyAsString)\n\t}\n\tif v, ok := aggs[\"doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCount)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Pipeline simple value --\n\n// AggregationPipelineSimpleValue is a simple value, returned e.g. by a\n// MovAvg aggregation.\ntype AggregationPipelineSimpleValue struct {\n\tAggregations\n\n\tValue         *float64               // `json:\"value\"`\n\tValueAsString string                 // `json:\"value_as_string\"`\n\tMeta          map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationPipelineSimpleValue structure.\nfunc (a *AggregationPipelineSimpleValue) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"value\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Value)\n\t}\n\tif v, ok := aggs[\"value_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.ValueAsString)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Pipeline simple value --\n\n// AggregationPipelineBucketMetricValue is a value returned e.g. by a\n// MaxBucket aggregation.\ntype AggregationPipelineBucketMetricValue struct {\n\tAggregations\n\n\tKeys          []interface{}          // `json:\"keys\"`\n\tValue         *float64               // `json:\"value\"`\n\tValueAsString string                 // `json:\"value_as_string\"`\n\tMeta          map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationPipelineBucketMetricValue structure.\nfunc (a *AggregationPipelineBucketMetricValue) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"keys\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Keys)\n\t}\n\tif v, ok := aggs[\"value\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Value)\n\t}\n\tif v, ok := aggs[\"value_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.ValueAsString)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Pipeline derivative --\n\n// AggregationPipelineDerivative is the value returned by a\n// Derivative aggregation.\ntype AggregationPipelineDerivative struct {\n\tAggregations\n\n\tValue                   *float64               // `json:\"value\"`\n\tValueAsString           string                 // `json:\"value_as_string\"`\n\tNormalizedValue         *float64               // `json:\"normalized_value\"`\n\tNormalizedValueAsString string                 // `json:\"normalized_value_as_string\"`\n\tMeta                    map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationPipelineDerivative structure.\nfunc (a *AggregationPipelineDerivative) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"value\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Value)\n\t}\n\tif v, ok := aggs[\"value_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.ValueAsString)\n\t}\n\tif v, ok := aggs[\"normalized_value\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.NormalizedValue)\n\t}\n\tif v, ok := aggs[\"normalized_value_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.NormalizedValueAsString)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Pipeline stats metric --\n\n// AggregationPipelineStatsMetric is a simple value, returned e.g. by a\n// MovAvg aggregation.\ntype AggregationPipelineStatsMetric struct {\n\tAggregations\n\n\tCount         int64    // `json:\"count\"`\n\tCountAsString string   // `json:\"count_as_string\"`\n\tMin           *float64 // `json:\"min\"`\n\tMinAsString   string   // `json:\"min_as_string\"`\n\tMax           *float64 // `json:\"max\"`\n\tMaxAsString   string   // `json:\"max_as_string\"`\n\tAvg           *float64 // `json:\"avg\"`\n\tAvgAsString   string   // `json:\"avg_as_string\"`\n\tSum           *float64 // `json:\"sum\"`\n\tSumAsString   string   // `json:\"sum_as_string\"`\n\n\tMeta map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationPipelineStatsMetric structure.\nfunc (a *AggregationPipelineStatsMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Count)\n\t}\n\tif v, ok := aggs[\"count_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.CountAsString)\n\t}\n\tif v, ok := aggs[\"min\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Min)\n\t}\n\tif v, ok := aggs[\"min_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.MinAsString)\n\t}\n\tif v, ok := aggs[\"max\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Max)\n\t}\n\tif v, ok := aggs[\"max_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.MaxAsString)\n\t}\n\tif v, ok := aggs[\"avg\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Avg)\n\t}\n\tif v, ok := aggs[\"avg_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.AvgAsString)\n\t}\n\tif v, ok := aggs[\"sum\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Sum)\n\t}\n\tif v, ok := aggs[\"sum_as_string\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.SumAsString)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Pipeline percentiles\n\n// AggregationPipelinePercentilesMetric is the value returned by a pipeline\n// percentiles Metric aggregation\ntype AggregationPipelinePercentilesMetric struct {\n\tAggregations\n\n\tValues map[string]float64     // `json:\"values\"`\n\tMeta   map[string]interface{} // `json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationPipelinePercentilesMetric structure.\nfunc (a *AggregationPipelinePercentilesMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"values\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Values)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// -- Composite key items --\n\n// AggregationBucketCompositeItems implements the response structure\n// for a bucket aggregation of type composite.\ntype AggregationBucketCompositeItems struct {\n\tAggregations\n\n\tBuckets  []*AggregationBucketCompositeItem //`json:\"buckets\"`\n\tMeta     map[string]interface{}            // `json:\"meta,omitempty\"`\n\tAfterKey map[string]interface{}            // `json:\"after_key,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketCompositeItems structure.\nfunc (a *AggregationBucketCompositeItems) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"buckets\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Buckets)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\tif v, ok := aggs[\"after_key\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.AfterKey)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationBucketCompositeItem is a single bucket of an AggregationBucketCompositeItems structure.\ntype AggregationBucketCompositeItem struct {\n\tAggregations\n\n\tKey      map[string]interface{} //`json:\"key\"`\n\tDocCount int64                  //`json:\"doc_count\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationBucketCompositeItem structure.\nfunc (a *AggregationBucketCompositeItem) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tdec := json.NewDecoder(bytes.NewReader(data))\n\tdec.UseNumber()\n\tif err := dec.Decode(&aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"key\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Key)\n\t}\n\tif v, ok := aggs[\"doc_count\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.DocCount)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationScriptedMetric is the value return by a scripted metric aggregation.\n// Value maybe one of map[string]interface{}/[]interface{}/string/bool/json.Number\ntype AggregationScriptedMetric struct {\n\tAggregations\n\n\tValue interface{}            //`json:\"value\"`\n\tMeta  map[string]interface{} //`json:\"meta,omitempty\"`\n}\n\n// UnmarshalJSON decodes JSON data and initializes an AggregationScriptedMetric structure.\nfunc (a *AggregationScriptedMetric) UnmarshalJSON(data []byte) error {\n\tvar aggs map[string]json.RawMessage\n\tif err := json.Unmarshal(data, &aggs); err != nil {\n\t\treturn err\n\t}\n\tif v, ok := aggs[\"value\"]; ok && v != nil {\n\t\tdecoder := json.NewDecoder(bytes.NewReader(v))\n\t\tdecoder.UseNumber()\n\t\tdecoder.Decode(&a.Value)\n\t}\n\tif v, ok := aggs[\"meta\"]; ok && v != nil {\n\t\tjson.Unmarshal(v, &a.Meta)\n\t}\n\ta.Aggregations = aggs\n\treturn nil\n}\n\n// AggregationTopMetricsItems is the value returned by the top metrics aggregation\ntype AggregationTopMetricsItems struct {\n\tAggregations\n\n\tTop []AggregationTopMetricsItem `json:\"top\"`\n}\n\n// AggregationTopMetricsItem is a set of metrics returned for the top document or documents\ntype AggregationTopMetricsItem struct {\n\tSort    []interface{}          `json:\"sort\"`    // sort information\n\tMetrics map[string]interface{} `json:\"metrics\"` // returned metrics\n}\n"
  },
  {
    "path": "search_aggs_bucket_adjacency_matrix.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// AdjacencyMatrixAggregation returning a form of adjacency matrix.\n// The request provides a collection of named filter expressions,\n// similar to the filters aggregation request. Each bucket in the\n// response represents a non-empty cell in the matrix of intersecting filters.\n//\n// For details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-adjacency-matrix-aggregation.html\ntype AdjacencyMatrixAggregation struct {\n\tfilters         map[string]Query\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\n// NewAdjacencyMatrixAggregation initializes a new AdjacencyMatrixAggregation.\nfunc NewAdjacencyMatrixAggregation() *AdjacencyMatrixAggregation {\n\treturn &AdjacencyMatrixAggregation{\n\t\tfilters:         make(map[string]Query),\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\n// Filters adds the filter\nfunc (a *AdjacencyMatrixAggregation) Filters(name string, filter Query) *AdjacencyMatrixAggregation {\n\ta.filters[name] = filter\n\treturn a\n}\n\n// SubAggregation adds a sub-aggregation to this aggregation.\nfunc (a *AdjacencyMatrixAggregation) SubAggregation(name string, subAggregation Aggregation) *AdjacencyMatrixAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *AdjacencyMatrixAggregation) Meta(metaData map[string]interface{}) *AdjacencyMatrixAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *AdjacencyMatrixAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//  \"aggs\" : {\n\t//\t\t\"interactions\" : {\n\t//\t\t\t\"adjacency_matrix\" : {\n\t//\t\t\t\t\"filters\" : {\n\t//\t\t\t\t\t\"grpA\" : { \"terms\" : { \"accounts\" : [\"hillary\", \"sidney\"] }},\n\t//\t\t\t\t\t\"grpB\" : { \"terms\" : { \"accounts\" : [\"donald\", \"mitt\"] }},\n\t//\t\t\t\t\t\"grpC\" : { \"terms\" : { \"accounts\" : [\"vladimir\", \"nigel\"] }}\n\t//\t\t\t\t}\n\t//\t\t\t}\n\t//\t\t}\n\t//\t}\n\t// This method returns only the (outer) { \"adjacency_matrix\" : {} } part.\n\n\tsource := make(map[string]interface{})\n\tadjacencyMatrix := make(map[string]interface{})\n\tsource[\"adjacency_matrix\"] = adjacencyMatrix\n\n\tdict := make(map[string]interface{})\n\tfor key, filter := range a.filters {\n\t\tsrc, err := filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdict[key] = src\n\t}\n\tadjacencyMatrix[\"filters\"] = dict\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_adjacency_matrix_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestAdjacencyMatrixAggregationFilters(t *testing.T) {\n\tf1 := NewTermQuery(\"accounts\", \"sydney\")\n\tf2 := NewTermQuery(\"accounts\", \"mitt\")\n\tf3 := NewTermQuery(\"accounts\", \"nigel\")\n\tagg := NewAdjacencyMatrixAggregation().Filters(\"grpA\", f1).Filters(\"grpB\", f2).Filters(\"grpC\", f3)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"adjacency_matrix\":{\"filters\":{\"grpA\":{\"term\":{\"accounts\":\"sydney\"}},\"grpB\":{\"term\":{\"accounts\":\"mitt\"}},\"grpC\":{\"term\":{\"accounts\":\"nigel\"}}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestAdjacencyMatrixAggregationWithSubAggregation(t *testing.T) {\n\tavgPriceAgg := NewAvgAggregation().Field(\"price\")\n\tf1 := NewTermQuery(\"accounts\", \"sydney\")\n\tf2 := NewTermQuery(\"accounts\", \"mitt\")\n\tf3 := NewTermQuery(\"accounts\", \"nigel\")\n\tagg := NewAdjacencyMatrixAggregation().SubAggregation(\"avg_price\", avgPriceAgg).Filters(\"grpA\", f1).Filters(\"grpB\", f2).Filters(\"grpC\", f3)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"adjacency_matrix\":{\"filters\":{\"grpA\":{\"term\":{\"accounts\":\"sydney\"}},\"grpB\":{\"term\":{\"accounts\":\"mitt\"}},\"grpC\":{\"term\":{\"accounts\":\"nigel\"}}}},\"aggregations\":{\"avg_price\":{\"avg\":{\"field\":\"price\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestAdjacencyMatrixAggregationWithMetaData(t *testing.T) {\n\tf1 := NewTermQuery(\"accounts\", \"sydney\")\n\tf2 := NewTermQuery(\"accounts\", \"mitt\")\n\tf3 := NewTermQuery(\"accounts\", \"nigel\")\n\tagg := NewAdjacencyMatrixAggregation().Filters(\"grpA\", f1).Filters(\"grpB\", f2).Filters(\"grpC\", f3).Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"adjacency_matrix\":{\"filters\":{\"grpA\":{\"term\":{\"accounts\":\"sydney\"}},\"grpB\":{\"term\":{\"accounts\":\"mitt\"}},\"grpC\":{\"term\":{\"accounts\":\"nigel\"}}}},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_auto_date_histogram.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// AutoDateHistogramAggregation is a multi-bucket aggregation similar to the\n// histogram except it can only be applied on date values, and the buckets num can bin pointed.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.3/search-aggregations-bucket-autodatehistogram-aggregation.html\ntype AutoDateHistogramAggregation struct {\n\tfield           string\n\tscript          *Script\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\n\tbuckets         int\n\tminDocCount     *int64\n\ttimeZone        string\n\tformat          string\n\tminimumInterval string\n}\n\n// NewAutoDateHistogramAggregation creates a new AutoDateHistogramAggregation.\nfunc NewAutoDateHistogramAggregation() *AutoDateHistogramAggregation {\n\treturn &AutoDateHistogramAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\n// Field on which the aggregation is processed.\nfunc (a *AutoDateHistogramAggregation) Field(field string) *AutoDateHistogramAggregation {\n\ta.field = field\n\treturn a\n}\n\n// Script on which th\nfunc (a *AutoDateHistogramAggregation) Script(script *Script) *AutoDateHistogramAggregation {\n\ta.script = script\n\treturn a\n}\n\n// Missing configures the value to use when documents miss a value.\nfunc (a *AutoDateHistogramAggregation) Missing(missing interface{}) *AutoDateHistogramAggregation {\n\ta.missing = missing\n\treturn a\n}\n\n// SubAggregation sub aggregation\nfunc (a *AutoDateHistogramAggregation) SubAggregation(name string, subAggregation Aggregation) *AutoDateHistogramAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *AutoDateHistogramAggregation) Meta(metaData map[string]interface{}) *AutoDateHistogramAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// Buckets buckets num by which the aggregation gets processed.\nfunc (a *AutoDateHistogramAggregation) Buckets(buckets int) *AutoDateHistogramAggregation {\n\ta.buckets = buckets\n\treturn a\n}\n\n// MinDocCount sets the minimum document count per bucket.\n// Buckets with less documents than this min value will not be returned.\nfunc (a *AutoDateHistogramAggregation) MinDocCount(minDocCount int64) *AutoDateHistogramAggregation {\n\ta.minDocCount = &minDocCount\n\treturn a\n}\n\n// TimeZone sets the timezone in which to translate dates before computing buckets.\nfunc (a *AutoDateHistogramAggregation) TimeZone(timeZone string) *AutoDateHistogramAggregation {\n\ta.timeZone = timeZone\n\treturn a\n}\n\n// Format sets the format to use for dates.\nfunc (a *AutoDateHistogramAggregation) Format(format string) *AutoDateHistogramAggregation {\n\ta.format = format\n\treturn a\n}\n\n// MinimumInterval accepted units for minimum_interval are: year/month/day/hour/minute/second\nfunc (a *AutoDateHistogramAggregation) MinimumInterval(interval string) *AutoDateHistogramAggregation {\n\ta.minimumInterval = interval\n\treturn a\n}\n\n// Source source for AutoDateHistogramAggregation\nfunc (a *AutoDateHistogramAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\" : {\n\t//         \"articles_over_time\" : {\n\t//             \"auto_date_histogram\" : {\n\t//                 \"field\" : \"date\",\n\t//                 \"buckets\" : 10\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the { \"auto_date_histogram\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"auto_date_histogram\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\tif a.buckets > 0 {\n\t\topts[\"buckets\"] = a.buckets\n\t}\n\n\tif a.minDocCount != nil {\n\t\topts[\"min_doc_count\"] = *a.minDocCount\n\t}\n\tif a.timeZone != \"\" {\n\t\topts[\"time_zone\"] = a.timeZone\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.minimumInterval != \"\" {\n\t\topts[\"minimum_interval\"] = a.minimumInterval\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_auto_date_histogram_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestAutoDateHistogramAggregation(t *testing.T) {\n\tagg := NewAutoDateHistogramAggregation().\n\t\tField(\"date\").\n\t\tBuckets(10)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"auto_date_histogram\":{\"buckets\":10,\"field\":\"date\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestAutoDateHistogramAggregationWithFormat(t *testing.T) {\n\tagg := NewAutoDateHistogramAggregation().Field(\"date\").Format(\"yyyy-MM-dd\").Buckets(5)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"auto_date_histogram\":{\"buckets\":5,\"field\":\"date\",\"format\":\"yyyy-MM-dd\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestAutoDateHistogramAggregationWithMissing(t *testing.T) {\n\tagg := NewAutoDateHistogramAggregation().Field(\"date\").Missing(\"1900\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"auto_date_histogram\":{\"field\":\"date\",\"missing\":\"1900\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_children.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// ChildrenAggregation is a special single bucket aggregation that enables\n// aggregating from buckets on parent document types to buckets on child documents.\n// It is available from 1.4.0.Beta1 upwards.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-children-aggregation.html\ntype ChildrenAggregation struct {\n\ttyp             string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewChildrenAggregation() *ChildrenAggregation {\n\treturn &ChildrenAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *ChildrenAggregation) Type(typ string) *ChildrenAggregation {\n\ta.typ = typ\n\treturn a\n}\n\nfunc (a *ChildrenAggregation) SubAggregation(name string, subAggregation Aggregation) *ChildrenAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *ChildrenAggregation) Meta(metaData map[string]interface{}) *ChildrenAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *ChildrenAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"to-answers\" : {\n\t//        \"children\": {\n\t//          \"type\" : \"answer\"\n\t//        }\n\t//      }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"type\" : ... } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"children\"] = opts\n\topts[\"type\"] = a.typ\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_children_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestChildrenAggregation(t *testing.T) {\n\tagg := NewChildrenAggregation().Type(\"answer\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"children\":{\"type\":\"answer\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestChildrenAggregationWithSubAggregation(t *testing.T) {\n\tsubAgg := NewTermsAggregation().Field(\"owner.display_name\").Size(10)\n\tagg := NewChildrenAggregation().Type(\"answer\")\n\tagg = agg.SubAggregation(\"top-names\", subAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"top-names\":{\"terms\":{\"field\":\"owner.display_name\",\"size\":10}}},\"children\":{\"type\":\"answer\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_composite.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// CompositeAggregation is a multi-bucket values source based aggregation\n// that can be used to calculate unique composite values from source documents.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-composite-aggregation.html\n// for details.\ntype CompositeAggregation struct {\n\tafter           map[string]interface{}\n\tsize            *int\n\tsources         []CompositeAggregationValuesSource\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\n// NewCompositeAggregation creates a new CompositeAggregation.\nfunc NewCompositeAggregation() *CompositeAggregation {\n\treturn &CompositeAggregation{\n\t\tsources:         make([]CompositeAggregationValuesSource, 0),\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\n// Size represents the number of composite buckets to return.\n// Defaults to 10 as of Elasticsearch 6.1.\nfunc (a *CompositeAggregation) Size(size int) *CompositeAggregation {\n\ta.size = &size\n\treturn a\n}\n\n// AggregateAfter sets the values that indicate which composite bucket this\n// request should \"aggregate after\".\nfunc (a *CompositeAggregation) AggregateAfter(after map[string]interface{}) *CompositeAggregation {\n\ta.after = after\n\treturn a\n}\n\n// Sources specifies the list of CompositeAggregationValuesSource instances to\n// use in the aggregation.\nfunc (a *CompositeAggregation) Sources(sources ...CompositeAggregationValuesSource) *CompositeAggregation {\n\ta.sources = append(a.sources, sources...)\n\treturn a\n}\n\n// SubAggregations of this aggregation.\nfunc (a *CompositeAggregation) SubAggregation(name string, subAggregation Aggregation) *CompositeAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *CompositeAggregation) Meta(metaData map[string]interface{}) *CompositeAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// Source returns the serializable JSON for this aggregation.\nfunc (a *CompositeAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\" : {\n\t//         \"my_composite_agg\" : {\n\t//             \"composite\" : {\n\t//                 \"sources\": [\n\t//\t\t\t\t      {\"my_term\": { \"terms\": { \"field\": \"product\" }}},\n\t//\t\t\t\t      {\"my_histo\": { \"histogram\": { \"field\": \"price\", \"interval\": 5 }}},\n\t//\t\t\t\t      {\"my_date\": { \"date_histogram\": { \"field\": \"timestamp\", \"interval\": \"1d\" }}},\n\t//                 ],\n\t//                 \"size\" : 10,\n\t//                 \"after\" : [\"a\", 2, \"c\"]\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the { \"histogram\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"composite\"] = opts\n\n\tsources := make([]interface{}, len(a.sources))\n\tfor i, s := range a.sources {\n\t\tsrc, err := s.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsources[i] = src\n\t}\n\topts[\"sources\"] = sources\n\n\tif a.size != nil {\n\t\topts[\"size\"] = *a.size\n\t}\n\n\tif a.after != nil {\n\t\topts[\"after\"] = a.after\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n\n// -- Generic interface for CompositeAggregationValues --\n\n// CompositeAggregationValuesSource specifies the interface that\n// all implementations for CompositeAggregation's Sources method\n// need to implement.\n//\n// The different implementations are described in\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-composite-aggregation.html#_values_source_2.\ntype CompositeAggregationValuesSource interface {\n\tSource() (interface{}, error)\n}\n\n// -- CompositeAggregationTermsValuesSource --\n\n// CompositeAggregationTermsValuesSource is a source for the CompositeAggregation that handles terms\n// it works very similar to a terms aggregation with slightly different syntax\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-composite-aggregation.html#_terms\n// for details.\ntype CompositeAggregationTermsValuesSource struct {\n\tname          string\n\tfield         string\n\tscript        *Script\n\tvalueType     string\n\tmissing       interface{}\n\tmissingBucket *bool\n\torder         string\n}\n\n// NewCompositeAggregationTermsValuesSource creates and initializes\n// a new CompositeAggregationTermsValuesSource.\nfunc NewCompositeAggregationTermsValuesSource(name string) *CompositeAggregationTermsValuesSource {\n\treturn &CompositeAggregationTermsValuesSource{\n\t\tname: name,\n\t}\n}\n\n// Field to use for this source.\nfunc (a *CompositeAggregationTermsValuesSource) Field(field string) *CompositeAggregationTermsValuesSource {\n\ta.field = field\n\treturn a\n}\n\n// Script to use for this source.\nfunc (a *CompositeAggregationTermsValuesSource) Script(script *Script) *CompositeAggregationTermsValuesSource {\n\ta.script = script\n\treturn a\n}\n\n// ValueType specifies the type of values produced by this source,\n// e.g. \"string\" or \"date\".\nfunc (a *CompositeAggregationTermsValuesSource) ValueType(valueType string) *CompositeAggregationTermsValuesSource {\n\ta.valueType = valueType\n\treturn a\n}\n\n// Order specifies the order in the values produced by this source.\n// It can be either \"asc\" or \"desc\".\nfunc (a *CompositeAggregationTermsValuesSource) Order(order string) *CompositeAggregationTermsValuesSource {\n\ta.order = order\n\treturn a\n}\n\n// Asc ensures the order of the values produced is ascending.\nfunc (a *CompositeAggregationTermsValuesSource) Asc() *CompositeAggregationTermsValuesSource {\n\ta.order = \"asc\"\n\treturn a\n}\n\n// Desc ensures the order of the values produced is descending.\nfunc (a *CompositeAggregationTermsValuesSource) Desc() *CompositeAggregationTermsValuesSource {\n\ta.order = \"desc\"\n\treturn a\n}\n\n// Missing specifies the value to use when the source finds a missing\n// value in a document.\n//\n// Deprecated: Use MissingBucket instead.\nfunc (a *CompositeAggregationTermsValuesSource) Missing(missing interface{}) *CompositeAggregationTermsValuesSource {\n\ta.missing = missing\n\treturn a\n}\n\n// MissingBucket, if true, will create an explicit null bucket which represents\n// documents with missing values.\nfunc (a *CompositeAggregationTermsValuesSource) MissingBucket(missingBucket bool) *CompositeAggregationTermsValuesSource {\n\ta.missingBucket = &missingBucket\n\treturn a\n}\n\n// Source returns the serializable JSON for this values source.\nfunc (a *CompositeAggregationTermsValuesSource) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tname := make(map[string]interface{})\n\tsource[a.name] = name\n\tvalues := make(map[string]interface{})\n\tname[\"terms\"] = values\n\n\t// field\n\tif a.field != \"\" {\n\t\tvalues[\"field\"] = a.field\n\t}\n\n\t// script\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvalues[\"script\"] = src\n\t}\n\n\t// missing\n\tif a.missing != nil {\n\t\tvalues[\"missing\"] = a.missing\n\t}\n\n\t// missing_bucket\n\tif a.missingBucket != nil {\n\t\tvalues[\"missing_bucket\"] = *a.missingBucket\n\t}\n\n\t// value_type\n\tif a.valueType != \"\" {\n\t\tvalues[\"value_type\"] = a.valueType\n\t}\n\n\t// order\n\tif a.order != \"\" {\n\t\tvalues[\"order\"] = a.order\n\t}\n\n\treturn source, nil\n\n}\n\n// -- CompositeAggregationHistogramValuesSource --\n\n// CompositeAggregationHistogramValuesSource is a source for the CompositeAggregation that handles histograms\n// it works very similar to a terms histogram with slightly different syntax\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-composite-aggregation.html#_histogram\n// for details.\ntype CompositeAggregationHistogramValuesSource struct {\n\tname          string\n\tfield         string\n\tscript        *Script\n\tvalueType     string\n\tmissing       interface{}\n\tmissingBucket *bool\n\torder         string\n\tinterval      float64\n}\n\n// NewCompositeAggregationHistogramValuesSource creates and initializes\n// a new CompositeAggregationHistogramValuesSource.\nfunc NewCompositeAggregationHistogramValuesSource(name string, interval float64) *CompositeAggregationHistogramValuesSource {\n\treturn &CompositeAggregationHistogramValuesSource{\n\t\tname:     name,\n\t\tinterval: interval,\n\t}\n}\n\n// Field to use for this source.\nfunc (a *CompositeAggregationHistogramValuesSource) Field(field string) *CompositeAggregationHistogramValuesSource {\n\ta.field = field\n\treturn a\n}\n\n// Script to use for this source.\nfunc (a *CompositeAggregationHistogramValuesSource) Script(script *Script) *CompositeAggregationHistogramValuesSource {\n\ta.script = script\n\treturn a\n}\n\n// ValueType specifies the type of values produced by this source,\n// e.g. \"string\" or \"date\".\nfunc (a *CompositeAggregationHistogramValuesSource) ValueType(valueType string) *CompositeAggregationHistogramValuesSource {\n\ta.valueType = valueType\n\treturn a\n}\n\n// Missing specifies the value to use when the source finds a missing\n// value in a document.\n//\n// Deprecated: Use MissingBucket instead.\nfunc (a *CompositeAggregationHistogramValuesSource) Missing(missing interface{}) *CompositeAggregationHistogramValuesSource {\n\ta.missing = missing\n\treturn a\n}\n\n// MissingBucket, if true, will create an explicit null bucket which represents\n// documents with missing values.\nfunc (a *CompositeAggregationHistogramValuesSource) MissingBucket(missingBucket bool) *CompositeAggregationHistogramValuesSource {\n\ta.missingBucket = &missingBucket\n\treturn a\n}\n\n// Order specifies the order in the values produced by this source.\n// It can be either \"asc\" or \"desc\".\nfunc (a *CompositeAggregationHistogramValuesSource) Order(order string) *CompositeAggregationHistogramValuesSource {\n\ta.order = order\n\treturn a\n}\n\n// Asc ensures the order of the values produced is ascending.\nfunc (a *CompositeAggregationHistogramValuesSource) Asc() *CompositeAggregationHistogramValuesSource {\n\ta.order = \"asc\"\n\treturn a\n}\n\n// Desc ensures the order of the values produced is descending.\nfunc (a *CompositeAggregationHistogramValuesSource) Desc() *CompositeAggregationHistogramValuesSource {\n\ta.order = \"desc\"\n\treturn a\n}\n\n// Interval specifies the interval to use.\nfunc (a *CompositeAggregationHistogramValuesSource) Interval(interval float64) *CompositeAggregationHistogramValuesSource {\n\ta.interval = interval\n\treturn a\n}\n\n// Source returns the serializable JSON for this values source.\nfunc (a *CompositeAggregationHistogramValuesSource) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tname := make(map[string]interface{})\n\tsource[a.name] = name\n\tvalues := make(map[string]interface{})\n\tname[\"histogram\"] = values\n\n\t// field\n\tif a.field != \"\" {\n\t\tvalues[\"field\"] = a.field\n\t}\n\n\t// script\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvalues[\"script\"] = src\n\t}\n\n\t// missing\n\tif a.missing != nil {\n\t\tvalues[\"missing\"] = a.missing\n\t}\n\n\t// missing_bucket\n\tif a.missingBucket != nil {\n\t\tvalues[\"missing_bucket\"] = *a.missingBucket\n\t}\n\n\t// value_type\n\tif a.valueType != \"\" {\n\t\tvalues[\"value_type\"] = a.valueType\n\t}\n\n\t// order\n\tif a.order != \"\" {\n\t\tvalues[\"order\"] = a.order\n\t}\n\n\t// Histogram-related properties\n\tvalues[\"interval\"] = a.interval\n\n\treturn source, nil\n\n}\n\n// -- CompositeAggregationDateHistogramValuesSource --\n\n// CompositeAggregationDateHistogramValuesSource is a source for the CompositeAggregation that handles date histograms\n// it works very similar to a date histogram aggregation with slightly different syntax\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.4/search-aggregations-bucket-composite-aggregation.html#_date_histogram\n// for details.\ntype CompositeAggregationDateHistogramValuesSource struct {\n\tname             string\n\tfield            string\n\tscript           *Script\n\tvalueType        string\n\tmissing          interface{}\n\tmissingBucket    *bool\n\torder            string\n\tinterval         interface{}\n\tfixedInterval    interface{}\n\tcalendarInterval interface{}\n\tformat           string\n\ttimeZone         string\n}\n\n// NewCompositeAggregationDateHistogramValuesSource creates and initializes\n// a new CompositeAggregationDateHistogramValuesSource.\nfunc NewCompositeAggregationDateHistogramValuesSource(name string) *CompositeAggregationDateHistogramValuesSource {\n\treturn &CompositeAggregationDateHistogramValuesSource{\n\t\tname: name,\n\t}\n}\n\n// Field to use for this source.\nfunc (a *CompositeAggregationDateHistogramValuesSource) Field(field string) *CompositeAggregationDateHistogramValuesSource {\n\ta.field = field\n\treturn a\n}\n\n// Script to use for this source.\nfunc (a *CompositeAggregationDateHistogramValuesSource) Script(script *Script) *CompositeAggregationDateHistogramValuesSource {\n\ta.script = script\n\treturn a\n}\n\n// ValueType specifies the type of values produced by this source,\n// e.g. \"string\" or \"date\".\nfunc (a *CompositeAggregationDateHistogramValuesSource) ValueType(valueType string) *CompositeAggregationDateHistogramValuesSource {\n\ta.valueType = valueType\n\treturn a\n}\n\n// Missing specifies the value to use when the source finds a missing\n// value in a document.\n//\n// Deprecated: Use MissingBucket instead.\nfunc (a *CompositeAggregationDateHistogramValuesSource) Missing(missing interface{}) *CompositeAggregationDateHistogramValuesSource {\n\ta.missing = missing\n\treturn a\n}\n\n// MissingBucket, if true, will create an explicit null bucket which represents\n// documents with missing values.\nfunc (a *CompositeAggregationDateHistogramValuesSource) MissingBucket(missingBucket bool) *CompositeAggregationDateHistogramValuesSource {\n\ta.missingBucket = &missingBucket\n\treturn a\n}\n\n// Order specifies the order in the values produced by this source.\n// It can be either \"asc\" or \"desc\".\nfunc (a *CompositeAggregationDateHistogramValuesSource) Order(order string) *CompositeAggregationDateHistogramValuesSource {\n\ta.order = order\n\treturn a\n}\n\n// Asc ensures the order of the values produced is ascending.\nfunc (a *CompositeAggregationDateHistogramValuesSource) Asc() *CompositeAggregationDateHistogramValuesSource {\n\ta.order = \"asc\"\n\treturn a\n}\n\n// Desc ensures the order of the values produced is descending.\nfunc (a *CompositeAggregationDateHistogramValuesSource) Desc() *CompositeAggregationDateHistogramValuesSource {\n\ta.order = \"desc\"\n\treturn a\n}\n\n// Interval to use for the date histogram, e.g. \"1d\" or a numeric value like \"60\".\n//\n// Deprecated: Use FixedInterval or CalendarInterval instead.\nfunc (a *CompositeAggregationDateHistogramValuesSource) Interval(interval interface{}) *CompositeAggregationDateHistogramValuesSource {\n\ta.interval = interval\n\treturn a\n}\n\n// FixedInterval to use for the date histogram, e.g. \"1d\" or a numeric value like \"60\".\nfunc (a *CompositeAggregationDateHistogramValuesSource) FixedInterval(fixedInterval interface{}) *CompositeAggregationDateHistogramValuesSource {\n\ta.fixedInterval = fixedInterval\n\treturn a\n}\n\n// CalendarInterval to use for the date histogram, e.g. \"1d\" or a numeric value like \"60\".\nfunc (a *CompositeAggregationDateHistogramValuesSource) CalendarInterval(calendarInterval interface{}) *CompositeAggregationDateHistogramValuesSource {\n\ta.calendarInterval = calendarInterval\n\treturn a\n}\n\n// Format to use for the date histogram, e.g. \"strict_date_optional_time\"\nfunc (a *CompositeAggregationDateHistogramValuesSource) Format(format string) *CompositeAggregationDateHistogramValuesSource {\n\ta.format = format\n\treturn a\n}\n\n// TimeZone to use for the dates.\nfunc (a *CompositeAggregationDateHistogramValuesSource) TimeZone(timeZone string) *CompositeAggregationDateHistogramValuesSource {\n\ta.timeZone = timeZone\n\treturn a\n}\n\n// Source returns the serializable JSON for this values source.\nfunc (a *CompositeAggregationDateHistogramValuesSource) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tname := make(map[string]interface{})\n\tsource[a.name] = name\n\tvalues := make(map[string]interface{})\n\tname[\"date_histogram\"] = values\n\n\t// field\n\tif a.field != \"\" {\n\t\tvalues[\"field\"] = a.field\n\t}\n\n\t// script\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tvalues[\"script\"] = src\n\t}\n\n\t// missing\n\tif a.missing != nil {\n\t\tvalues[\"missing\"] = a.missing\n\t}\n\n\t// missing_bucket\n\tif a.missingBucket != nil {\n\t\tvalues[\"missing_bucket\"] = *a.missingBucket\n\t}\n\n\t// value_type\n\tif a.valueType != \"\" {\n\t\tvalues[\"value_type\"] = a.valueType\n\t}\n\n\t// order\n\tif a.order != \"\" {\n\t\tvalues[\"order\"] = a.order\n\t}\n\n\tif a.format != \"\" {\n\t\tvalues[\"format\"] = a.format\n\t}\n\n\t// DateHistogram-related properties\n\tif v := a.interval; v != nil {\n\t\tvalues[\"interval\"] = v\n\t}\n\tif v := a.fixedInterval; v != nil {\n\t\tvalues[\"fixed_interval\"] = v\n\t}\n\tif v := a.calendarInterval; v != nil {\n\t\tvalues[\"calendar_interval\"] = v\n\t}\n\n\t// timeZone\n\tif a.timeZone != \"\" {\n\t\tvalues[\"time_zone\"] = a.timeZone\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_composite_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestCompositeAggregation(t *testing.T) {\n\tagg := NewCompositeAggregation().\n\t\tSources(\n\t\t\tNewCompositeAggregationTermsValuesSource(\"my_terms\").Field(\"a_term\").Missing(\"N/A\").Order(\"asc\"),\n\t\t\tNewCompositeAggregationHistogramValuesSource(\"my_histogram\", 5).Field(\"price\").Asc(),\n\t\t\tNewCompositeAggregationDateHistogramValuesSource(\"my_date_histogram\").CalendarInterval(\"1d\").Field(\"purchase_date\").Desc(),\n\t\t).\n\t\tSize(10).\n\t\tAggregateAfter(map[string]interface{}{\n\t\t\t\"my_terms\":          \"1\",\n\t\t\t\"my_histogram\":      2,\n\t\t\t\"my_date_histogram\": \"3\",\n\t\t})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"composite\":{\"after\":{\"my_date_histogram\":\"3\",\"my_histogram\":2,\"my_terms\":\"1\"},\"size\":10,\"sources\":[{\"my_terms\":{\"terms\":{\"field\":\"a_term\",\"missing\":\"N/A\",\"order\":\"asc\"}}},{\"my_histogram\":{\"histogram\":{\"field\":\"price\",\"interval\":5,\"order\":\"asc\"}}},{\"my_date_histogram\":{\"date_histogram\":{\"calendar_interval\":\"1d\",\"field\":\"purchase_date\",\"order\":\"desc\"}}}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCompositeAggregationTermsValuesSource(t *testing.T) {\n\tin := NewCompositeAggregationTermsValuesSource(\"products\").\n\t\tScript(NewScript(\"doc['product'].value\").Lang(\"painless\"))\n\tsrc, err := in.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"products\":{\"terms\":{\"script\":{\"lang\":\"painless\",\"source\":\"doc['product'].value\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCompositeAggregationHistogramValuesSource(t *testing.T) {\n\tin := NewCompositeAggregationHistogramValuesSource(\"histo\", 5).\n\t\tField(\"price\")\n\tsrc, err := in.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"histo\":{\"histogram\":{\"field\":\"price\",\"interval\":5}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCompositeAggregationDateHistogramValuesSourceWithCalendarInterval(t *testing.T) {\n\tin := NewCompositeAggregationDateHistogramValuesSource(\"date\").CalendarInterval(\"1d\").\n\t\tField(\"timestamp\").\n\t\tFormat(\"strict_date_optional_time\")\n\tsrc, err := in.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date\":{\"date_histogram\":{\"calendar_interval\":\"1d\",\"field\":\"timestamp\",\"format\":\"strict_date_optional_time\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCompositeAggregationDateHistogramValuesSourceWithFixedInterval(t *testing.T) {\n\tin := NewCompositeAggregationDateHistogramValuesSource(\"date\").FixedInterval(\"1d\").\n\t\tField(\"timestamp\").\n\t\tFormat(\"strict_date_optional_time\")\n\tsrc, err := in.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date\":{\"date_histogram\":{\"field\":\"timestamp\",\"fixed_interval\":\"1d\",\"format\":\"strict_date_optional_time\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_count_thresholds.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// BucketCountThresholds is used in e.g. terms and significant text aggregations.\ntype BucketCountThresholds struct {\n\tMinDocCount      *int64\n\tShardMinDocCount *int64\n\tRequiredSize     *int\n\tShardSize        *int\n}\n"
  },
  {
    "path": "search_aggs_bucket_date_histogram.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// DateHistogramAggregation is a multi-bucket aggregation similar to the\n// histogram except it can only be applied on date values.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-datehistogram-aggregation.html\ntype DateHistogramAggregation struct {\n\tfield           string\n\tscript          *Script\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\n\tinterval          string\n\tfixedInterval     string\n\tcalendarInterval  string\n\torder             string\n\torderAsc          bool\n\tminDocCount       *int64\n\textendedBoundsMin interface{}\n\textendedBoundsMax interface{}\n\ttimeZone          string\n\tformat            string\n\toffset            string\n\tkeyed             *bool\n}\n\n// NewDateHistogramAggregation creates a new DateHistogramAggregation.\nfunc NewDateHistogramAggregation() *DateHistogramAggregation {\n\treturn &DateHistogramAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\n// Field on which the aggregation is processed.\nfunc (a *DateHistogramAggregation) Field(field string) *DateHistogramAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *DateHistogramAggregation) Script(script *Script) *DateHistogramAggregation {\n\ta.script = script\n\treturn a\n}\n\n// Missing configures the value to use when documents miss a value.\nfunc (a *DateHistogramAggregation) Missing(missing interface{}) *DateHistogramAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *DateHistogramAggregation) SubAggregation(name string, subAggregation Aggregation) *DateHistogramAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *DateHistogramAggregation) Meta(metaData map[string]interface{}) *DateHistogramAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// Interval by which the aggregation gets processed. This field\n// will be replaced by the two FixedInterval and CalendarInterval\n// fields (see below).\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.4/search-aggregations-bucket-datehistogram-aggregation.html\n//\n// Deprecated: This field will be removed in the future.\nfunc (a *DateHistogramAggregation) Interval(interval string) *DateHistogramAggregation {\n\ta.interval = interval\n\treturn a\n}\n\n// FixedInterval by which the aggregation gets processed.\n//\n// Allowed values are: \"year\", \"1y\", \"quarter\", \"1q\", \"month\", \"1M\",\n// \"week\", \"1w\", \"day\", \"1d\", \"hour\", \"1h\", \"minute\", \"1m\", \"second\",\n// or \"1s\". It also supports time settings like \"1.5h\".\n//\n// These units are not calendar-aware and are simply multiples of\n// fixed, SI units. This is mutually exclusive with CalendarInterval.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.4/search-aggregations-bucket-datehistogram-aggregation.html\nfunc (a *DateHistogramAggregation) FixedInterval(fixedInterval string) *DateHistogramAggregation {\n\ta.fixedInterval = fixedInterval\n\treturn a\n}\n\n// CalendarInterval by which the aggregation gets processed.\n//\n// Allowed values are: \"year\" (\"1y\", \"y\"), \"quarter\" (\"1q\", \"q\"),\n// \"month\" (\"1M\", \"M\"), \"week\" (\"1w\", \"w\"), \"day\" (\"d\", \"1d\")\n//\n// These units are calendar-aware, meaning they respect leap\n// additions, variable days per month etc. This is mutually\n// exclusive with FixedInterval.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.4/search-aggregations-bucket-datehistogram-aggregation.html\nfunc (a *DateHistogramAggregation) CalendarInterval(calendarInterval string) *DateHistogramAggregation {\n\ta.calendarInterval = calendarInterval\n\treturn a\n}\n\n// Order specifies the sort order. Valid values for order are:\n// \"_key\", \"_count\", a sub-aggregation name, or a sub-aggregation name\n// with a metric.\nfunc (a *DateHistogramAggregation) Order(order string, asc bool) *DateHistogramAggregation {\n\ta.order = order\n\ta.orderAsc = asc\n\treturn a\n}\n\nfunc (a *DateHistogramAggregation) OrderByCount(asc bool) *DateHistogramAggregation {\n\t// \"order\" : { \"_count\" : \"asc\" }\n\ta.order = \"_count\"\n\ta.orderAsc = asc\n\treturn a\n}\n\nfunc (a *DateHistogramAggregation) OrderByCountAsc() *DateHistogramAggregation {\n\treturn a.OrderByCount(true)\n}\n\nfunc (a *DateHistogramAggregation) OrderByCountDesc() *DateHistogramAggregation {\n\treturn a.OrderByCount(false)\n}\n\nfunc (a *DateHistogramAggregation) OrderByKey(asc bool) *DateHistogramAggregation {\n\t// \"order\" : { \"_key\" : \"asc\" }\n\ta.order = \"_key\"\n\ta.orderAsc = asc\n\treturn a\n}\n\nfunc (a *DateHistogramAggregation) OrderByKeyAsc() *DateHistogramAggregation {\n\treturn a.OrderByKey(true)\n}\n\nfunc (a *DateHistogramAggregation) OrderByKeyDesc() *DateHistogramAggregation {\n\treturn a.OrderByKey(false)\n}\n\n// OrderByAggregation creates a bucket ordering strategy which sorts buckets\n// based on a single-valued calc get.\nfunc (a *DateHistogramAggregation) OrderByAggregation(aggName string, asc bool) *DateHistogramAggregation {\n\t// {\n\t//     \"aggs\" : {\n\t//         \"genders\" : {\n\t//             \"terms\" : {\n\t//                 \"field\" : \"gender\",\n\t//                 \"order\" : { \"avg_height\" : \"desc\" }\n\t//             },\n\t//             \"aggs\" : {\n\t//                 \"avg_height\" : { \"avg\" : { \"field\" : \"height\" } }\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\ta.order = aggName\n\ta.orderAsc = asc\n\treturn a\n}\n\n// OrderByAggregationAndMetric creates a bucket ordering strategy which\n// sorts buckets based on a multi-valued calc get.\nfunc (a *DateHistogramAggregation) OrderByAggregationAndMetric(aggName, metric string, asc bool) *DateHistogramAggregation {\n\t// {\n\t//     \"aggs\" : {\n\t//         \"genders\" : {\n\t//             \"terms\" : {\n\t//                 \"field\" : \"gender\",\n\t//                 \"order\" : { \"height_stats.avg\" : \"desc\" }\n\t//             },\n\t//             \"aggs\" : {\n\t//                 \"height_stats\" : { \"stats\" : { \"field\" : \"height\" } }\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\ta.order = aggName + \".\" + metric\n\ta.orderAsc = asc\n\treturn a\n}\n\n// MinDocCount sets the minimum document count per bucket.\n// Buckets with less documents than this min value will not be returned.\nfunc (a *DateHistogramAggregation) MinDocCount(minDocCount int64) *DateHistogramAggregation {\n\ta.minDocCount = &minDocCount\n\treturn a\n}\n\n// TimeZone sets the timezone in which to translate dates before computing buckets.\nfunc (a *DateHistogramAggregation) TimeZone(timeZone string) *DateHistogramAggregation {\n\ta.timeZone = timeZone\n\treturn a\n}\n\n// Format sets the format to use for dates.\nfunc (a *DateHistogramAggregation) Format(format string) *DateHistogramAggregation {\n\ta.format = format\n\treturn a\n}\n\n// Offset sets the offset of time intervals in the histogram, e.g. \"+6h\".\nfunc (a *DateHistogramAggregation) Offset(offset string) *DateHistogramAggregation {\n\ta.offset = offset\n\treturn a\n}\n\n// ExtendedBounds accepts int, int64, string, or time.Time values.\n// In case the lower value in the histogram would be greater than min or the\n// upper value would be less than max, empty buckets will be generated.\nfunc (a *DateHistogramAggregation) ExtendedBounds(min, max interface{}) *DateHistogramAggregation {\n\ta.extendedBoundsMin = min\n\ta.extendedBoundsMax = max\n\treturn a\n}\n\n// ExtendedBoundsMin accepts int, int64, string, or time.Time values.\nfunc (a *DateHistogramAggregation) ExtendedBoundsMin(min interface{}) *DateHistogramAggregation {\n\ta.extendedBoundsMin = min\n\treturn a\n}\n\n// ExtendedBoundsMax accepts int, int64, string, or time.Time values.\nfunc (a *DateHistogramAggregation) ExtendedBoundsMax(max interface{}) *DateHistogramAggregation {\n\ta.extendedBoundsMax = max\n\treturn a\n}\n\n// Keyed specifies whether to return the results with a keyed response (or not).\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-datehistogram-aggregation.html#_keyed_response_3.\nfunc (a *DateHistogramAggregation) Keyed(keyed bool) *DateHistogramAggregation {\n\ta.keyed = &keyed\n\treturn a\n}\n\nfunc (a *DateHistogramAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\" : {\n\t//         \"articles_over_time\" : {\n\t//             \"date_histogram\" : {\n\t//                 \"field\" : \"date\",\n\t//                 \"fixed_interval\" : \"month\"\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the { \"date_histogram\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"date_histogram\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\tif s := a.interval; s != \"\" {\n\t\topts[\"interval\"] = s\n\t}\n\tif s := a.fixedInterval; s != \"\" {\n\t\topts[\"fixed_interval\"] = s\n\t}\n\tif s := a.calendarInterval; s != \"\" {\n\t\topts[\"calendar_interval\"] = s\n\t}\n\n\tif a.minDocCount != nil {\n\t\topts[\"min_doc_count\"] = *a.minDocCount\n\t}\n\tif a.order != \"\" {\n\t\to := make(map[string]interface{})\n\t\tif a.orderAsc {\n\t\t\to[a.order] = \"asc\"\n\t\t} else {\n\t\t\to[a.order] = \"desc\"\n\t\t}\n\t\topts[\"order\"] = o\n\t}\n\tif a.timeZone != \"\" {\n\t\topts[\"time_zone\"] = a.timeZone\n\t}\n\tif a.offset != \"\" {\n\t\topts[\"offset\"] = a.offset\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.extendedBoundsMin != nil || a.extendedBoundsMax != nil {\n\t\tbounds := make(map[string]interface{})\n\t\tif a.extendedBoundsMin != nil {\n\t\t\tbounds[\"min\"] = a.extendedBoundsMin\n\t\t}\n\t\tif a.extendedBoundsMax != nil {\n\t\t\tbounds[\"max\"] = a.extendedBoundsMax\n\t\t}\n\t\topts[\"extended_bounds\"] = bounds\n\t}\n\tif a.keyed != nil {\n\t\topts[\"keyed\"] = *a.keyed\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_date_histogram_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestDateHistogramAggregationLegacyInterval(t *testing.T) {\n\tagg := NewDateHistogramAggregation().\n\t\tField(\"date\").\n\t\tInterval(\"week\").\n\t\tFormat(\"yyyy-MM\").\n\t\tTimeZone(\"UTC\").\n\t\tOffset(\"+6h\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_histogram\":{\"field\":\"date\",\"format\":\"yyyy-MM\",\"interval\":\"week\",\"offset\":\"+6h\",\"time_zone\":\"UTC\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateHistogramAggregationFixed(t *testing.T) {\n\tagg := NewDateHistogramAggregation().\n\t\tField(\"date\").\n\t\tFixedInterval(\"month\").\n\t\tFormat(\"yyyy-MM\").\n\t\tTimeZone(\"UTC\").\n\t\tOffset(\"+6h\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_histogram\":{\"field\":\"date\",\"fixed_interval\":\"month\",\"format\":\"yyyy-MM\",\"offset\":\"+6h\",\"time_zone\":\"UTC\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateHistogramAggregationCalendar(t *testing.T) {\n\tagg := NewDateHistogramAggregation().\n\t\tField(\"date\").\n\t\tCalendarInterval(\"1d\").\n\t\tFormat(\"yyyy-MM\").\n\t\tTimeZone(\"UTC\").\n\t\tOffset(\"+6h\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_histogram\":{\"calendar_interval\":\"1d\",\"field\":\"date\",\"format\":\"yyyy-MM\",\"offset\":\"+6h\",\"time_zone\":\"UTC\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateHistogramAggregationWithKeyedResponse(t *testing.T) {\n\tagg := NewDateHistogramAggregation().Field(\"date\").CalendarInterval(\"year\").Missing(\"1900\").Keyed(true)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_histogram\":{\"calendar_interval\":\"year\",\"field\":\"date\",\"keyed\":true,\"missing\":\"1900\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateHistogramAggregationWithMissing(t *testing.T) {\n\tagg := NewDateHistogramAggregation().Field(\"date\").CalendarInterval(\"year\").Missing(\"1900\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_histogram\":{\"calendar_interval\":\"year\",\"field\":\"date\",\"missing\":\"1900\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_date_range.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"time\"\n)\n\n// DateRangeAggregation is a range aggregation that is dedicated for\n// date values. The main difference between this aggregation and the\n// normal range aggregation is that the from and to values can be expressed\n// in Date Math expressions, and it is also possible to specify a\n// date format by which the from and to response fields will be returned.\n// Note that this aggregration includes the from value and excludes the to\n// value for each range.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-daterange-aggregation.html\ntype DateRangeAggregation struct {\n\tfield           string\n\tscript          *Script\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\tkeyed           *bool\n\tunmapped        *bool\n\ttimeZone        string\n\tformat          string\n\tentries         []DateRangeAggregationEntry\n}\n\ntype DateRangeAggregationEntry struct {\n\tKey  string\n\tFrom interface{}\n\tTo   interface{}\n}\n\nfunc NewDateRangeAggregation() *DateRangeAggregation {\n\treturn &DateRangeAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t\tentries:         make([]DateRangeAggregationEntry, 0),\n\t}\n}\n\nfunc (a *DateRangeAggregation) Field(field string) *DateRangeAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) Script(script *Script) *DateRangeAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) SubAggregation(name string, subAggregation Aggregation) *DateRangeAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *DateRangeAggregation) Meta(metaData map[string]interface{}) *DateRangeAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) Keyed(keyed bool) *DateRangeAggregation {\n\ta.keyed = &keyed\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) Unmapped(unmapped bool) *DateRangeAggregation {\n\ta.unmapped = &unmapped\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) TimeZone(timeZone string) *DateRangeAggregation {\n\ta.timeZone = timeZone\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) Format(format string) *DateRangeAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) AddRange(from, to interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{From: from, To: to})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) AddRangeWithKey(key string, from, to interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: from, To: to})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) AddUnboundedTo(from interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{From: from, To: nil})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) AddUnboundedToWithKey(key string, from interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: from, To: nil})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) AddUnboundedFrom(to interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{From: nil, To: to})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) AddUnboundedFromWithKey(key string, to interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: nil, To: to})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) Lt(to interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{From: nil, To: to})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) LtWithKey(key string, to interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: nil, To: to})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) Between(from, to interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{From: from, To: to})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) BetweenWithKey(key string, from, to interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: from, To: to})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) Gt(from interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{From: from, To: nil})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) GtWithKey(key string, from interface{}) *DateRangeAggregation {\n\ta.entries = append(a.entries, DateRangeAggregationEntry{Key: key, From: from, To: nil})\n\treturn a\n}\n\nfunc (a *DateRangeAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\" : {\n\t//         \"range\" : {\n\t//             \"date_range\": {\n\t//                 \"field\": \"date\",\n\t//                 \"format\": \"MM-yyy\",\n\t//                 \"ranges\": [\n\t//                     { \"to\": \"now-10M/M\" },\n\t//                     { \"from\": \"now-10M/M\" }\n\t//                 ]\n\t//             }\n\t//         }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the { \"date_range\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"date_range\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\n\tif a.keyed != nil {\n\t\topts[\"keyed\"] = *a.keyed\n\t}\n\tif a.unmapped != nil {\n\t\topts[\"unmapped\"] = *a.unmapped\n\t}\n\tif a.timeZone != \"\" {\n\t\topts[\"time_zone\"] = a.timeZone\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\n\tvar ranges []interface{}\n\tfor _, ent := range a.entries {\n\t\tr := make(map[string]interface{})\n\t\tif ent.Key != \"\" {\n\t\t\tr[\"key\"] = ent.Key\n\t\t}\n\t\tif ent.From != nil {\n\t\t\tswitch from := ent.From.(type) {\n\t\t\tcase int, int16, int32, int64, float32, float64:\n\t\t\t\tr[\"from\"] = from\n\t\t\tcase *int, *int16, *int32, *int64, *float32, *float64:\n\t\t\t\tr[\"from\"] = from\n\t\t\tcase time.Time:\n\t\t\t\tr[\"from\"] = from.Format(time.RFC3339)\n\t\t\tcase *time.Time:\n\t\t\t\tr[\"from\"] = from.Format(time.RFC3339)\n\t\t\tcase string:\n\t\t\t\tr[\"from\"] = from\n\t\t\tcase *string:\n\t\t\t\tr[\"from\"] = from\n\t\t\t}\n\t\t}\n\t\tif ent.To != nil {\n\t\t\tswitch to := ent.To.(type) {\n\t\t\tcase int, int16, int32, int64, float32, float64:\n\t\t\t\tr[\"to\"] = to\n\t\t\tcase *int, *int16, *int32, *int64, *float32, *float64:\n\t\t\t\tr[\"to\"] = to\n\t\t\tcase time.Time:\n\t\t\t\tr[\"to\"] = to.Format(time.RFC3339)\n\t\t\tcase *time.Time:\n\t\t\t\tr[\"to\"] = to.Format(time.RFC3339)\n\t\t\tcase string:\n\t\t\t\tr[\"to\"] = to\n\t\t\tcase *string:\n\t\t\t\tr[\"to\"] = to\n\t\t\t}\n\t\t}\n\t\tranges = append(ranges, r)\n\t}\n\topts[\"ranges\"] = ranges\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_date_range_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestDateRangeAggregation(t *testing.T) {\n\tagg := NewDateRangeAggregation().Field(\"created_at\").TimeZone(\"UTC\")\n\tagg = agg.AddRange(nil, \"2012-12-31\")\n\tagg = agg.AddRange(\"2013-01-01\", \"2013-12-31\")\n\tagg = agg.AddRange(\"2014-01-01\", nil)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_range\":{\"field\":\"created_at\",\"ranges\":[{\"to\":\"2012-12-31\"},{\"from\":\"2013-01-01\",\"to\":\"2013-12-31\"},{\"from\":\"2014-01-01\"}],\"time_zone\":\"UTC\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateRangeAggregationWithPointers(t *testing.T) {\n\td1 := \"2012-12-31\"\n\td2 := \"2013-01-01\"\n\td3 := \"2013-12-31\"\n\td4 := \"2014-01-01\"\n\n\tagg := NewDateRangeAggregation().Field(\"created_at\")\n\tagg = agg.AddRange(nil, &d1)\n\tagg = agg.AddRange(d2, &d3)\n\tagg = agg.AddRange(d4, nil)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_range\":{\"field\":\"created_at\",\"ranges\":[{\"to\":\"2012-12-31\"},{\"from\":\"2013-01-01\",\"to\":\"2013-12-31\"},{\"from\":\"2014-01-01\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateRangeAggregationWithUnbounded(t *testing.T) {\n\tagg := NewDateRangeAggregation().Field(\"created_at\").\n\t\tAddUnboundedFrom(\"2012-12-31\").\n\t\tAddRange(\"2013-01-01\", \"2013-12-31\").\n\t\tAddUnboundedTo(\"2014-01-01\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_range\":{\"field\":\"created_at\",\"ranges\":[{\"to\":\"2012-12-31\"},{\"from\":\"2013-01-01\",\"to\":\"2013-12-31\"},{\"from\":\"2014-01-01\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateRangeAggregationWithLtAndCo(t *testing.T) {\n\tagg := NewDateRangeAggregation().Field(\"created_at\").\n\t\tLt(\"2012-12-31\").\n\t\tBetween(\"2013-01-01\", \"2013-12-31\").\n\t\tGt(\"2014-01-01\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_range\":{\"field\":\"created_at\",\"ranges\":[{\"to\":\"2012-12-31\"},{\"from\":\"2013-01-01\",\"to\":\"2013-12-31\"},{\"from\":\"2014-01-01\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateRangeAggregationWithKeyedFlag(t *testing.T) {\n\tagg := NewDateRangeAggregation().Field(\"created_at\").\n\t\tKeyed(true).\n\t\tLt(\"2012-12-31\").\n\t\tBetween(\"2013-01-01\", \"2013-12-31\").\n\t\tGt(\"2014-01-01\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_range\":{\"field\":\"created_at\",\"keyed\":true,\"ranges\":[{\"to\":\"2012-12-31\"},{\"from\":\"2013-01-01\",\"to\":\"2013-12-31\"},{\"from\":\"2014-01-01\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateRangeAggregationWithKeys(t *testing.T) {\n\tagg := NewDateRangeAggregation().Field(\"created_at\").\n\t\tKeyed(true).\n\t\tLtWithKey(\"pre-2012\", \"2012-12-31\").\n\t\tBetweenWithKey(\"2013\", \"2013-01-01\", \"2013-12-31\").\n\t\tGtWithKey(\"post-2013\", \"2014-01-01\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_range\":{\"field\":\"created_at\",\"keyed\":true,\"ranges\":[{\"key\":\"pre-2012\",\"to\":\"2012-12-31\"},{\"from\":\"2013-01-01\",\"key\":\"2013\",\"to\":\"2013-12-31\"},{\"from\":\"2014-01-01\",\"key\":\"post-2013\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDateRangeAggregationWithSpecialNames(t *testing.T) {\n\tagg := NewDateRangeAggregation().Field(\"created_at\").\n\t\tAddRange(\"now-10M/M\", \"now+10M/M\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"date_range\":{\"field\":\"created_at\",\"ranges\":[{\"from\":\"now-10M/M\",\"to\":\"now+10M/M\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_diversified_sampler.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// DiversifiedSamplerAggregation Like the ‘sampler` aggregation this is a filtering aggregation used to limit any\n// sub aggregations’ processing to a sample of the top-scoring documents. The diversified_sampler aggregation adds\n// the ability to limit the number of matches that share a common value such as an \"author\".\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-diversified-sampler-aggregation.html\ntype DiversifiedSamplerAggregation struct {\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\tfield           string\n\tscript          *Script\n\tshardSize       int\n\tmaxDocsPerValue int\n\texecutionHint   string\n}\n\nfunc NewDiversifiedSamplerAggregation() *DiversifiedSamplerAggregation {\n\treturn &DiversifiedSamplerAggregation{\n\t\tshardSize:       -1,\n\t\tmaxDocsPerValue: -1,\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *DiversifiedSamplerAggregation) SubAggregation(name string, subAggregation Aggregation) *DiversifiedSamplerAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *DiversifiedSamplerAggregation) Meta(metaData map[string]interface{}) *DiversifiedSamplerAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// Field on which the aggregation is processed.\nfunc (a *DiversifiedSamplerAggregation) Field(field string) *DiversifiedSamplerAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *DiversifiedSamplerAggregation) Script(script *Script) *DiversifiedSamplerAggregation {\n\ta.script = script\n\treturn a\n}\n\n// ShardSize sets the maximum number of docs returned from each shard.\nfunc (a *DiversifiedSamplerAggregation) ShardSize(shardSize int) *DiversifiedSamplerAggregation {\n\ta.shardSize = shardSize\n\treturn a\n}\n\nfunc (a *DiversifiedSamplerAggregation) MaxDocsPerValue(maxDocsPerValue int) *DiversifiedSamplerAggregation {\n\ta.maxDocsPerValue = maxDocsPerValue\n\treturn a\n}\n\nfunc (a *DiversifiedSamplerAggregation) ExecutionHint(hint string) *DiversifiedSamplerAggregation {\n\ta.executionHint = hint\n\treturn a\n}\n\nfunc (a *DiversifiedSamplerAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\": {\n\t//\t\t\t\"my_unbiased_sample\": {\n\t//\t\t\t\t\"diversified_sampler\": {\n\t//\t\t\t\t\t\"shard_size\": 200,\n\t//\t\t\t\t\t\"field\" : \"author\"\n\t//\t\t\t\t}\n\t//\t\t\t}\n\t//\t\t}\n\t// }\n\t//\n\t// This method returns only the { \"diversified_sampler\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"diversified_sampler\"] = opts\n\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.shardSize >= 0 {\n\t\topts[\"shard_size\"] = a.shardSize\n\t}\n\tif a.maxDocsPerValue >= 0 {\n\t\topts[\"max_docs_per_value\"] = a.maxDocsPerValue\n\t}\n\tif a.executionHint != \"\" {\n\t\topts[\"execution_hint\"] = a.executionHint\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_diversified_sampler_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestDiversifiedSamplerAggregation(t *testing.T) {\n\tkeywordsAgg := NewSignificantTermsAggregation().Field(\"text\")\n\tagg := NewDiversifiedSamplerAggregation().\n\t\tShardSize(200).\n\t\tField(\"author\").\n\t\tSubAggregation(\"keywords\", keywordsAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"keywords\":{\"significant_terms\":{\"field\":\"text\"}}},\"diversified_sampler\":{\"field\":\"author\",\"shard_size\":200}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_filter.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// FilterAggregation defines a single bucket of all the documents\n// in the current document set context that match a specified filter.\n// Often this will be used to narrow down the current aggregation context\n// to a specific set of documents.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-filter-aggregation.html\ntype FilterAggregation struct {\n\tfilter          Query\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewFilterAggregation() *FilterAggregation {\n\treturn &FilterAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *FilterAggregation) SubAggregation(name string, subAggregation Aggregation) *FilterAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *FilterAggregation) Meta(metaData map[string]interface{}) *FilterAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *FilterAggregation) Filter(filter Query) *FilterAggregation {\n\ta.filter = filter\n\treturn a\n}\n\nfunc (a *FilterAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//         \"in_stock_products\" : {\n\t//             \"filter\" : { \"range\" : { \"stock\" : { \"gt\" : 0 } } }\n\t//         }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"filter\" : {} } part.\n\n\tsrc, err := a.filter.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsource := make(map[string]interface{})\n\tsource[\"filter\"] = src\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_filter_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestFilterAggregation(t *testing.T) {\n\tfilter := NewRangeQuery(\"stock\").Gt(0)\n\tagg := NewFilterAggregation().Filter(filter)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"filter\":{\"range\":{\"stock\":{\"from\":0,\"include_lower\":false,\"include_upper\":true,\"to\":null}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFilterAggregationWithSubAggregation(t *testing.T) {\n\tavgPriceAgg := NewAvgAggregation().Field(\"price\")\n\tfilter := NewRangeQuery(\"stock\").Gt(0)\n\tagg := NewFilterAggregation().Filter(filter).\n\t\tSubAggregation(\"avg_price\", avgPriceAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"avg_price\":{\"avg\":{\"field\":\"price\"}}},\"filter\":{\"range\":{\"stock\":{\"from\":0,\"include_lower\":false,\"include_upper\":true,\"to\":null}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFilterAggregationWithMeta(t *testing.T) {\n\tfilter := NewRangeQuery(\"stock\").Gt(0)\n\tagg := NewFilterAggregation().Filter(filter).Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"filter\":{\"range\":{\"stock\":{\"from\":0,\"include_lower\":false,\"include_upper\":true,\"to\":null}}},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_filters.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"errors\"\n\n// FiltersAggregation defines a multi bucket aggregations where each bucket\n// is associated with a filter. Each bucket will collect all documents that\n// match its associated filter.\n//\n// Notice that the caller has to decide whether to add filters by name\n// (using FilterWithName) or unnamed filters (using Filter or Filters). One cannot\n// use both named and unnamed filters.\n//\n// For details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-filters-aggregation.html\ntype FiltersAggregation struct {\n\tunnamedFilters  []Query\n\tnamedFilters    map[string]Query\n\totherBucket     *bool\n\totherBucketKey  string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\n// NewFiltersAggregation initializes a new FiltersAggregation.\nfunc NewFiltersAggregation() *FiltersAggregation {\n\treturn &FiltersAggregation{\n\t\tunnamedFilters:  make([]Query, 0),\n\t\tnamedFilters:    make(map[string]Query),\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\n// Filter adds an unnamed filter. Notice that you can\n// either use named or unnamed filters, but not both.\nfunc (a *FiltersAggregation) Filter(filter Query) *FiltersAggregation {\n\ta.unnamedFilters = append(a.unnamedFilters, filter)\n\treturn a\n}\n\n// Filters adds one or more unnamed filters. Notice that you can\n// either use named or unnamed filters, but not both.\nfunc (a *FiltersAggregation) Filters(filters ...Query) *FiltersAggregation {\n\tif len(filters) > 0 {\n\t\ta.unnamedFilters = append(a.unnamedFilters, filters...)\n\t}\n\treturn a\n}\n\n// FilterWithName adds a filter with a specific name. Notice that you can\n// either use named or unnamed filters, but not both.\nfunc (a *FiltersAggregation) FilterWithName(name string, filter Query) *FiltersAggregation {\n\ta.namedFilters[name] = filter\n\treturn a\n}\n\n// OtherBucket indicates whether to include a bucket for documents not\n// matching any filter.\nfunc (a *FiltersAggregation) OtherBucket(otherBucket bool) *FiltersAggregation {\n\ta.otherBucket = &otherBucket\n\treturn a\n}\n\n// OtherBucketKey sets the key to use for the bucket for documents not\n// matching any filter.\nfunc (a *FiltersAggregation) OtherBucketKey(key string) *FiltersAggregation {\n\ta.otherBucketKey = key\n\treturn a\n}\n\n// SubAggregation adds a sub-aggregation to this aggregation.\nfunc (a *FiltersAggregation) SubAggregation(name string, subAggregation Aggregation) *FiltersAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *FiltersAggregation) Meta(metaData map[string]interface{}) *FiltersAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\n// If the aggregation is invalid, an error is returned. This may e.g. happen\n// if you mixed named and unnamed filters.\nfunc (a *FiltersAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//  \"aggs\" : {\n\t//    \"messages\" : {\n\t//      \"filters\" : {\n\t//        \"filters\" : {\n\t//          \"errors\" :   { \"term\" : { \"body\" : \"error\"   }},\n\t//          \"warnings\" : { \"term\" : { \"body\" : \"warning\" }}\n\t//        }\n\t//      }\n\t//    }\n\t//  }\n\t//\t}\n\t// This method returns only the (outer) { \"filters\" : {} } part.\n\n\tsource := make(map[string]interface{})\n\tfilters := make(map[string]interface{})\n\tsource[\"filters\"] = filters\n\n\tif len(a.unnamedFilters) > 0 && len(a.namedFilters) > 0 {\n\t\treturn nil, errors.New(\"elastic: use either named or unnamed filters with FiltersAggregation but not both\")\n\t}\n\n\tif len(a.unnamedFilters) > 0 {\n\t\tarr := make([]interface{}, len(a.unnamedFilters))\n\t\tfor i, filter := range a.unnamedFilters {\n\t\t\tsrc, err := filter.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tarr[i] = src\n\t\t}\n\t\tfilters[\"filters\"] = arr\n\t} else {\n\t\tdict := make(map[string]interface{})\n\t\tfor key, filter := range a.namedFilters {\n\t\t\tsrc, err := filter.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdict[key] = src\n\t\t}\n\t\tfilters[\"filters\"] = dict\n\t}\n\n\tif v := a.otherBucket; v != nil {\n\t\tfilters[\"other_bucket\"] = *v\n\t}\n\tif v := a.otherBucketKey; v != \"\" {\n\t\tfilters[\"other_bucket_key\"] = v\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_filters_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestFiltersAggregationFilters(t *testing.T) {\n\tf1 := NewRangeQuery(\"stock\").Gt(0)\n\tf2 := NewTermQuery(\"symbol\", \"GOOG\")\n\tagg := NewFiltersAggregation().Filters(f1, f2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"filters\":{\"filters\":[{\"range\":{\"stock\":{\"from\":0,\"include_lower\":false,\"include_upper\":true,\"to\":null}}},{\"term\":{\"symbol\":\"GOOG\"}}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFiltersAggregationFilterWithName(t *testing.T) {\n\tf1 := NewRangeQuery(\"stock\").Gt(0)\n\tf2 := NewTermQuery(\"symbol\", \"GOOG\")\n\tagg := NewFiltersAggregation().\n\t\tFilterWithName(\"f1\", f1).\n\t\tFilterWithName(\"f2\", f2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"filters\":{\"filters\":{\"f1\":{\"range\":{\"stock\":{\"from\":0,\"include_lower\":false,\"include_upper\":true,\"to\":null}}},\"f2\":{\"term\":{\"symbol\":\"GOOG\"}}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFiltersAggregationWithKeyedAndNonKeyedFilters(t *testing.T) {\n\tagg := NewFiltersAggregation().\n\t\tFilter(NewTermQuery(\"symbol\", \"MSFT\")).               // unnamed\n\t\tFilterWithName(\"one\", NewTermQuery(\"symbol\", \"GOOG\")) // named filter\n\t_, err := agg.Source()\n\tif err == nil {\n\t\tt.Fatal(\"expected error, got nil\")\n\t}\n}\n\nfunc TestFiltersAggregationWithOtherBuckets(t *testing.T) {\n\tagg := NewFiltersAggregation().\n\t\tFilterWithName(\"errors\", NewMatchQuery(\"body\", \"error\")).\n\t\tFilterWithName(\"warnings\", NewMatchQuery(\"body\", \"warnings\")).\n\t\tOtherBucket(true).\n\t\tOtherBucketKey(\"other\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"filters\":{\"filters\":{\"errors\":{\"match\":{\"body\":{\"query\":\"error\"}}},\"warnings\":{\"match\":{\"body\":{\"query\":\"warnings\"}}}},\"other_bucket\":true,\"other_bucket_key\":\"other\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFiltersAggregationWithSubAggregation(t *testing.T) {\n\tavgPriceAgg := NewAvgAggregation().Field(\"price\")\n\tf1 := NewRangeQuery(\"stock\").Gt(0)\n\tf2 := NewTermQuery(\"symbol\", \"GOOG\")\n\tagg := NewFiltersAggregation().Filters(f1, f2).SubAggregation(\"avg_price\", avgPriceAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"avg_price\":{\"avg\":{\"field\":\"price\"}}},\"filters\":{\"filters\":[{\"range\":{\"stock\":{\"from\":0,\"include_lower\":false,\"include_upper\":true,\"to\":null}}},{\"term\":{\"symbol\":\"GOOG\"}}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFiltersAggregationWithMetaData(t *testing.T) {\n\tf1 := NewRangeQuery(\"stock\").Gt(0)\n\tf2 := NewTermQuery(\"symbol\", \"GOOG\")\n\tagg := NewFiltersAggregation().Filters(f1, f2).Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"filters\":{\"filters\":[{\"range\":{\"stock\":{\"from\":0,\"include_lower\":false,\"include_upper\":true,\"to\":null}}},{\"term\":{\"symbol\":\"GOOG\"}}]},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_geo_distance.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// GeoDistanceAggregation is a multi-bucket aggregation that works on geo_point fields\n// and conceptually works very similar to the range aggregation.\n// The user can define a point of origin and a set of distance range buckets.\n// The aggregation evaluate the distance of each document value from\n// the origin point and determines the buckets it belongs to based on\n// the ranges (a document belongs to a bucket if the distance between the\n// document and the origin falls within the distance range of the bucket).\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-geodistance-aggregation.html\ntype GeoDistanceAggregation struct {\n\tfield           string\n\tunit            string\n\tdistanceType    string\n\tpoint           string\n\tranges          []geoDistAggRange\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\ntype geoDistAggRange struct {\n\tKey  string\n\tFrom interface{}\n\tTo   interface{}\n}\n\nfunc NewGeoDistanceAggregation() *GeoDistanceAggregation {\n\treturn &GeoDistanceAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t\tranges:          make([]geoDistAggRange, 0),\n\t}\n}\n\nfunc (a *GeoDistanceAggregation) Field(field string) *GeoDistanceAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) Unit(unit string) *GeoDistanceAggregation {\n\ta.unit = unit\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) DistanceType(distanceType string) *GeoDistanceAggregation {\n\ta.distanceType = distanceType\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) Point(latLon string) *GeoDistanceAggregation {\n\ta.point = latLon\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) SubAggregation(name string, subAggregation Aggregation) *GeoDistanceAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *GeoDistanceAggregation) Meta(metaData map[string]interface{}) *GeoDistanceAggregation {\n\ta.meta = metaData\n\treturn a\n}\nfunc (a *GeoDistanceAggregation) AddRange(from, to interface{}) *GeoDistanceAggregation {\n\ta.ranges = append(a.ranges, geoDistAggRange{From: from, To: to})\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) AddRangeWithKey(key string, from, to interface{}) *GeoDistanceAggregation {\n\ta.ranges = append(a.ranges, geoDistAggRange{Key: key, From: from, To: to})\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) AddUnboundedTo(from float64) *GeoDistanceAggregation {\n\ta.ranges = append(a.ranges, geoDistAggRange{From: from, To: nil})\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) AddUnboundedToWithKey(key string, from float64) *GeoDistanceAggregation {\n\ta.ranges = append(a.ranges, geoDistAggRange{Key: key, From: from, To: nil})\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) AddUnboundedFrom(to float64) *GeoDistanceAggregation {\n\ta.ranges = append(a.ranges, geoDistAggRange{From: nil, To: to})\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) AddUnboundedFromWithKey(key string, to float64) *GeoDistanceAggregation {\n\ta.ranges = append(a.ranges, geoDistAggRange{Key: key, From: nil, To: to})\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) Between(from, to interface{}) *GeoDistanceAggregation {\n\ta.ranges = append(a.ranges, geoDistAggRange{From: from, To: to})\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) BetweenWithKey(key string, from, to interface{}) *GeoDistanceAggregation {\n\ta.ranges = append(a.ranges, geoDistAggRange{Key: key, From: from, To: to})\n\treturn a\n}\n\nfunc (a *GeoDistanceAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//    \"aggs\" : {\n\t//        \"rings_around_amsterdam\" : {\n\t//            \"geo_distance\" : {\n\t//                \"field\" : \"location\",\n\t//                \"origin\" : \"52.3760, 4.894\",\n\t//                \"ranges\" : [\n\t//                    { \"to\" : 100 },\n\t//                    { \"from\" : 100, \"to\" : 300 },\n\t//                    { \"from\" : 300 }\n\t//                ]\n\t//            }\n\t//        }\n\t//    }\n\t// }\n\t//\n\t// This method returns only the { \"range\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"geo_distance\"] = opts\n\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.unit != \"\" {\n\t\topts[\"unit\"] = a.unit\n\t}\n\tif a.distanceType != \"\" {\n\t\topts[\"distance_type\"] = a.distanceType\n\t}\n\tif a.point != \"\" {\n\t\topts[\"origin\"] = a.point\n\t}\n\n\tvar ranges []interface{}\n\tfor _, ent := range a.ranges {\n\t\tr := make(map[string]interface{})\n\t\tif ent.Key != \"\" {\n\t\t\tr[\"key\"] = ent.Key\n\t\t}\n\t\tif ent.From != nil {\n\t\t\tswitch from := ent.From.(type) {\n\t\t\tcase int, int16, int32, int64, float32, float64:\n\t\t\t\tr[\"from\"] = from\n\t\t\tcase *int, *int16, *int32, *int64, *float32, *float64:\n\t\t\t\tr[\"from\"] = from\n\t\t\tcase string:\n\t\t\t\tr[\"from\"] = from\n\t\t\tcase *string:\n\t\t\t\tr[\"from\"] = from\n\t\t\t}\n\t\t}\n\t\tif ent.To != nil {\n\t\t\tswitch to := ent.To.(type) {\n\t\t\tcase int, int16, int32, int64, float32, float64:\n\t\t\t\tr[\"to\"] = to\n\t\t\tcase *int, *int16, *int32, *int64, *float32, *float64:\n\t\t\t\tr[\"to\"] = to\n\t\t\tcase string:\n\t\t\t\tr[\"to\"] = to\n\t\t\tcase *string:\n\t\t\t\tr[\"to\"] = to\n\t\t\t}\n\t\t}\n\t\tranges = append(ranges, r)\n\t}\n\topts[\"ranges\"] = ranges\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_geo_distance_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGeoDistanceAggregation(t *testing.T) {\n\tagg := NewGeoDistanceAggregation().Field(\"location\").Point(\"52.3760, 4.894\")\n\tagg = agg.AddRange(nil, 100)\n\tagg = agg.AddRange(100, 300)\n\tagg = agg.AddRange(300, nil)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_distance\":{\"field\":\"location\",\"origin\":\"52.3760, 4.894\",\"ranges\":[{\"to\":100},{\"from\":100,\"to\":300},{\"from\":300}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoDistanceAggregationWithPointers(t *testing.T) {\n\thundred := 100\n\tthreeHundred := 300\n\tagg := NewGeoDistanceAggregation().Field(\"location\").Point(\"52.3760, 4.894\")\n\tagg = agg.AddRange(nil, &hundred)\n\tagg = agg.AddRange(hundred, &threeHundred)\n\tagg = agg.AddRange(threeHundred, nil)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_distance\":{\"field\":\"location\",\"origin\":\"52.3760, 4.894\",\"ranges\":[{\"to\":100},{\"from\":100,\"to\":300},{\"from\":300}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoDistanceAggregationWithUnbounded(t *testing.T) {\n\tagg := NewGeoDistanceAggregation().Field(\"location\").Point(\"52.3760, 4.894\")\n\tagg = agg.AddUnboundedFrom(100)\n\tagg = agg.AddRange(100, 300)\n\tagg = agg.AddUnboundedTo(300)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_distance\":{\"field\":\"location\",\"origin\":\"52.3760, 4.894\",\"ranges\":[{\"to\":100},{\"from\":100,\"to\":300},{\"from\":300}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoDistanceAggregationWithMetaData(t *testing.T) {\n\tagg := NewGeoDistanceAggregation().Field(\"location\").Point(\"52.3760, 4.894\")\n\tagg = agg.AddRange(nil, 100)\n\tagg = agg.AddRange(100, 300)\n\tagg = agg.AddRange(300, nil)\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_distance\":{\"field\":\"location\",\"origin\":\"52.3760, 4.894\",\"ranges\":[{\"to\":100},{\"from\":100,\"to\":300},{\"from\":300}]},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_geohash_grid.go",
    "content": "package elastic\n\ntype GeoHashGridAggregation struct {\n\tfield           string\n\tprecision       interface{}\n\tsize            int\n\tshardSize       int\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewGeoHashGridAggregation() *GeoHashGridAggregation {\n\treturn &GeoHashGridAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t\tsize:            -1,\n\t\tshardSize:       -1,\n\t}\n}\n\nfunc (a *GeoHashGridAggregation) Field(field string) *GeoHashGridAggregation {\n\ta.field = field\n\treturn a\n}\n\n// Precision accepts the level as int value between 1 and 12 or Distance Units like \"2km\", \"5mi\" as described at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/common-options.html#distance-units and\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-geohashgrid-aggregation.html\nfunc (a *GeoHashGridAggregation) Precision(precision interface{}) *GeoHashGridAggregation {\n\ta.precision = precision\n\treturn a\n}\n\nfunc (a *GeoHashGridAggregation) Size(size int) *GeoHashGridAggregation {\n\ta.size = size\n\treturn a\n}\n\nfunc (a *GeoHashGridAggregation) ShardSize(shardSize int) *GeoHashGridAggregation {\n\ta.shardSize = shardSize\n\treturn a\n}\n\nfunc (a *GeoHashGridAggregation) SubAggregation(name string, subAggregation Aggregation) *GeoHashGridAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\nfunc (a *GeoHashGridAggregation) Meta(metaData map[string]interface{}) *GeoHashGridAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *GeoHashGridAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\": {\n\t//         \"new_york\": {\n\t//             \"geohash_grid\": {\n\t//                 \"field\": \"location\",\n\t//                 \"precision\": 5\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"geohash_grid\"] = opts\n\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\n\tif a.precision != nil {\n\t\topts[\"precision\"] = a.precision\n\t}\n\n\tif a.size != -1 {\n\t\topts[\"size\"] = a.size\n\t}\n\n\tif a.shardSize != -1 {\n\t\topts[\"shard_size\"] = a.shardSize\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_geohash_grid_test.go",
    "content": "package elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGeoHashGridAggregation(t *testing.T) {\n\tagg := NewGeoHashGridAggregation().Field(\"location\").Precision(5)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"Marshalling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geohash_grid\":{\"field\":\"location\",\"precision\":5}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoHashGridAggregation_PrecisionAsString(t *testing.T) {\n\tagg := NewGeoHashGridAggregation().Field(\"location\").Precision(\"2km\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"Marshalling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geohash_grid\":{\"field\":\"location\",\"precision\":\"2km\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoHashGridAggregationWithMetaData(t *testing.T) {\n\tagg := NewGeoHashGridAggregation().Field(\"location\").Precision(5)\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"Marshalling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geohash_grid\":{\"field\":\"location\",\"precision\":5},\"meta\":{\"name\":\"Oliver\"}}`\n\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoHashGridAggregationWithSize(t *testing.T) {\n\tagg := NewGeoHashGridAggregation().Field(\"location\").Precision(5).Size(5)\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"Marshalling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geohash_grid\":{\"field\":\"location\",\"precision\":5,\"size\":5},\"meta\":{\"name\":\"Oliver\"}}`\n\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoHashGridAggregationWithShardSize(t *testing.T) {\n\tagg := NewGeoHashGridAggregation().Field(\"location\").Precision(5).ShardSize(5)\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"Marshalling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geohash_grid\":{\"field\":\"location\",\"precision\":5,\"shard_size\":5},\"meta\":{\"name\":\"Oliver\"}}`\n\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_geotile_grid.go",
    "content": "package elastic\n\nimport \"errors\"\n\ntype GeoTileGridAggregation struct {\n\tfield           string\n\tprecision       int\n\tsize            int\n\tshardSize       int\n\tbounds          *BoundingBox\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\n// NewGeoTileGridAggregation Create new bucket aggregation of Geotile grid type\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-geotilegrid-aggregation.html\nfunc NewGeoTileGridAggregation() *GeoTileGridAggregation {\n\treturn &GeoTileGridAggregation{\n\t\tprecision:       -1,\n\t\tsize:            -1,\n\t\tshardSize:       -1,\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\n// Field The name of the field indexed with GeoPoints. Mandatory.\nfunc (a *GeoTileGridAggregation) Field(field string) *GeoTileGridAggregation {\n\ta.field = field\n\treturn a\n}\n\n// Precision The integer zoom of the key used to define cells/buckets in the results. Defaults to 7. Values outside of [0,29] will be rejected. Optional.\nfunc (a *GeoTileGridAggregation) Precision(precision int) *GeoTileGridAggregation {\n\ta.precision = precision\n\treturn a\n}\n\n// Size The maximum number of buckets to return in the result structure. Optional.\nfunc (a *GeoTileGridAggregation) Size(size int) *GeoTileGridAggregation {\n\ta.size = size\n\treturn a\n}\n\n// ShardSize The maximum number of buckets to return from each shard. Optional.\nfunc (a *GeoTileGridAggregation) ShardSize(shardSize int) *GeoTileGridAggregation {\n\ta.shardSize = shardSize\n\treturn a\n}\n\n// Bounds The bounding box to filter the points in the bucket. Optional.\nfunc (a *GeoTileGridAggregation) Bounds(boundingBox BoundingBox) *GeoTileGridAggregation {\n\ta.bounds = &boundingBox\n\treturn a\n}\n\n// SubAggregation Adds a sub-aggregation to this aggregation.\nfunc (a *GeoTileGridAggregation) SubAggregation(name string, subAggregation Aggregation) *GeoTileGridAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta Sets the meta data to be included in the aggregation response.\nfunc (a *GeoTileGridAggregation) Meta(metaData map[string]interface{}) *GeoTileGridAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *GeoTileGridAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"geotile_grid\"] = opts\n\n\tif a.field == \"\" {\n\t\treturn nil, errors.New(\"elastic: 'field' is a mandatory parameter\")\n\t}\n\topts[\"field\"] = a.field\n\n\tif a.precision != -1 {\n\t\topts[\"precision\"] = a.precision\n\t}\n\n\tif a.size != -1 {\n\t\topts[\"size\"] = a.size\n\t}\n\n\tif a.shardSize != -1 {\n\t\topts[\"shard_size\"] = a.shardSize\n\t}\n\n\tif a.bounds != nil {\n\t\topts[\"bounds\"] = *a.bounds\n\t}\n\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n\n}\n\n// BoundingBox bounding box\ntype BoundingBox struct {\n\tTopLeft     GeoPoint `json:\"top_left\"`\n\tBottomRight GeoPoint `json:\"bottom_right\"`\n}\n"
  },
  {
    "path": "search_aggs_bucket_geotile_grid_test.go",
    "content": "package elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGeoTileGridAggregation(t *testing.T) {\n\tbounds := BoundingBox{\n\t\tTopLeft: GeoPoint{\n\t\t\tLat: 55.145984,\n\t\t\tLon: 82.75195,\n\t\t},\n\t\tBottomRight: GeoPoint{\n\t\t\tLat: 54.830199,\n\t\t\tLon: 83.143839,\n\t\t},\n\t}\n\tagg := NewGeoTileGridAggregation().\n\t\tField(\"location\").\n\t\tPrecision(12).\n\t\tSize(3).\n\t\tShardSize(5).\n\t\tBounds(bounds).\n\t\tMeta(map[string]interface{}{\"city\": \"Novosibirsk\"})\n\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"Marshalling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geotile_grid\":{\"bounds\":{\"top_left\":{\"lat\":55.145984,\"lon\":82.75195},\"bottom_right\":{\"lat\":54.830199,\"lon\":83.143839}},\"field\":\"location\",\"precision\":12,\"shard_size\":5,\"size\":3},\"meta\":{\"city\":\"Novosibirsk\"}}`\n\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_global.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// GlobalAggregation defines a single bucket of all the documents within\n// the search execution context. This context is defined by the indices\n// and the document types you’re searching on, but is not influenced\n// by the search query itself.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-global-aggregation.html\ntype GlobalAggregation struct {\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewGlobalAggregation() *GlobalAggregation {\n\treturn &GlobalAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *GlobalAggregation) SubAggregation(name string, subAggregation Aggregation) *GlobalAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *GlobalAggregation) Meta(metaData map[string]interface{}) *GlobalAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *GlobalAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//         \"all_products\" : {\n\t//             \"global\" : {},\n\t//             \"aggs\" : {\n\t//                 \"avg_price\" : { \"avg\" : { \"field\" : \"price\" } }\n\t//             }\n\t//         }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"global\" : {} } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"global\"] = opts\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_global_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGlobalAggregation(t *testing.T) {\n\tagg := NewGlobalAggregation()\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"global\":{}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGlobalAggregationWithMetaData(t *testing.T) {\n\tagg := NewGlobalAggregation().Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"global\":{},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_histogram.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// HistogramAggregation is a multi-bucket values source based aggregation\n// that can be applied on numeric values extracted from the documents.\n// It dynamically builds fixed size (a.k.a. interval) buckets over the\n// values.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-histogram-aggregation.html\ntype HistogramAggregation struct {\n\tfield           string\n\tscript          *Script\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\n\tinterval    float64\n\torder       string\n\torderAsc    bool\n\tminDocCount *int64\n\tminBounds   *float64\n\tmaxBounds   *float64\n\toffset      *float64\n}\n\nfunc NewHistogramAggregation() *HistogramAggregation {\n\treturn &HistogramAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *HistogramAggregation) Field(field string) *HistogramAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *HistogramAggregation) Script(script *Script) *HistogramAggregation {\n\ta.script = script\n\treturn a\n}\n\n// Missing configures the value to use when documents miss a value.\nfunc (a *HistogramAggregation) Missing(missing interface{}) *HistogramAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *HistogramAggregation) SubAggregation(name string, subAggregation Aggregation) *HistogramAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *HistogramAggregation) Meta(metaData map[string]interface{}) *HistogramAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// Interval for this builder, must be greater than 0.\nfunc (a *HistogramAggregation) Interval(interval float64) *HistogramAggregation {\n\ta.interval = interval\n\treturn a\n}\n\n// Order specifies the sort order. Valid values for order are:\n// \"_key\", \"_count\", a sub-aggregation name, or a sub-aggregation name\n// with a metric.\nfunc (a *HistogramAggregation) Order(order string, asc bool) *HistogramAggregation {\n\ta.order = order\n\ta.orderAsc = asc\n\treturn a\n}\n\nfunc (a *HistogramAggregation) OrderByCount(asc bool) *HistogramAggregation {\n\t// \"order\" : { \"_count\" : \"asc\" }\n\ta.order = \"_count\"\n\ta.orderAsc = asc\n\treturn a\n}\n\nfunc (a *HistogramAggregation) OrderByCountAsc() *HistogramAggregation {\n\treturn a.OrderByCount(true)\n}\n\nfunc (a *HistogramAggregation) OrderByCountDesc() *HistogramAggregation {\n\treturn a.OrderByCount(false)\n}\n\nfunc (a *HistogramAggregation) OrderByKey(asc bool) *HistogramAggregation {\n\t// \"order\" : { \"_key\" : \"asc\" }\n\ta.order = \"_key\"\n\ta.orderAsc = asc\n\treturn a\n}\n\nfunc (a *HistogramAggregation) OrderByKeyAsc() *HistogramAggregation {\n\treturn a.OrderByKey(true)\n}\n\nfunc (a *HistogramAggregation) OrderByKeyDesc() *HistogramAggregation {\n\treturn a.OrderByKey(false)\n}\n\n// OrderByAggregation creates a bucket ordering strategy which sorts buckets\n// based on a single-valued calc get.\nfunc (a *HistogramAggregation) OrderByAggregation(aggName string, asc bool) *HistogramAggregation {\n\t// {\n\t//     \"aggs\" : {\n\t//         \"genders\" : {\n\t//             \"terms\" : {\n\t//                 \"field\" : \"gender\",\n\t//                 \"order\" : { \"avg_height\" : \"desc\" }\n\t//             },\n\t//             \"aggs\" : {\n\t//                 \"avg_height\" : { \"avg\" : { \"field\" : \"height\" } }\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\ta.order = aggName\n\ta.orderAsc = asc\n\treturn a\n}\n\n// OrderByAggregationAndMetric creates a bucket ordering strategy which\n// sorts buckets based on a multi-valued calc get.\nfunc (a *HistogramAggregation) OrderByAggregationAndMetric(aggName, metric string, asc bool) *HistogramAggregation {\n\t// {\n\t//     \"aggs\" : {\n\t//         \"genders\" : {\n\t//             \"terms\" : {\n\t//                 \"field\" : \"gender\",\n\t//                 \"order\" : { \"height_stats.avg\" : \"desc\" }\n\t//             },\n\t//             \"aggs\" : {\n\t//                 \"height_stats\" : { \"stats\" : { \"field\" : \"height\" } }\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\ta.order = aggName + \".\" + metric\n\ta.orderAsc = asc\n\treturn a\n}\n\nfunc (a *HistogramAggregation) MinDocCount(minDocCount int64) *HistogramAggregation {\n\ta.minDocCount = &minDocCount\n\treturn a\n}\n\nfunc (a *HistogramAggregation) ExtendedBounds(min, max float64) *HistogramAggregation {\n\ta.minBounds = &min\n\ta.maxBounds = &max\n\treturn a\n}\n\nfunc (a *HistogramAggregation) ExtendedBoundsMin(min float64) *HistogramAggregation {\n\ta.minBounds = &min\n\treturn a\n}\n\nfunc (a *HistogramAggregation) MinBounds(min float64) *HistogramAggregation {\n\ta.minBounds = &min\n\treturn a\n}\n\nfunc (a *HistogramAggregation) ExtendedBoundsMax(max float64) *HistogramAggregation {\n\ta.maxBounds = &max\n\treturn a\n}\n\nfunc (a *HistogramAggregation) MaxBounds(max float64) *HistogramAggregation {\n\ta.maxBounds = &max\n\treturn a\n}\n\n// Offset into the histogram\nfunc (a *HistogramAggregation) Offset(offset float64) *HistogramAggregation {\n\ta.offset = &offset\n\treturn a\n}\n\nfunc (a *HistogramAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\" : {\n\t//         \"prices\" : {\n\t//             \"histogram\" : {\n\t//                 \"field\" : \"price\",\n\t//                 \"interval\" : 50\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the { \"histogram\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"histogram\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\topts[\"interval\"] = a.interval\n\tif a.order != \"\" {\n\t\to := make(map[string]interface{})\n\t\tif a.orderAsc {\n\t\t\to[a.order] = \"asc\"\n\t\t} else {\n\t\t\to[a.order] = \"desc\"\n\t\t}\n\t\topts[\"order\"] = o\n\t}\n\tif a.offset != nil {\n\t\topts[\"offset\"] = *a.offset\n\t}\n\tif a.minDocCount != nil {\n\t\topts[\"min_doc_count\"] = *a.minDocCount\n\t}\n\tif a.minBounds != nil || a.maxBounds != nil {\n\t\tbounds := make(map[string]interface{})\n\t\tif a.minBounds != nil {\n\t\t\tbounds[\"min\"] = a.minBounds\n\t\t}\n\t\tif a.maxBounds != nil {\n\t\t\tbounds[\"max\"] = a.maxBounds\n\t\t}\n\t\topts[\"extended_bounds\"] = bounds\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_histogram_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestHistogramAggregation(t *testing.T) {\n\tagg := NewHistogramAggregation().Field(\"price\").Interval(50)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"histogram\":{\"field\":\"price\",\"interval\":50}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHistogramAggregationWithMetaData(t *testing.T) {\n\tagg := NewHistogramAggregation().Field(\"price\").Offset(10).Interval(50).Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"histogram\":{\"field\":\"price\",\"interval\":50,\"offset\":10},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHistogramAggregationWithMissing(t *testing.T) {\n\tagg := NewHistogramAggregation().Field(\"price\").Interval(50).Missing(\"n/a\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"histogram\":{\"field\":\"price\",\"interval\":50,\"missing\":\"n/a\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_ip_range.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// IPRangeAggregation is a range aggregation that is dedicated for\n// IP addresses.\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-iprange-aggregation.html\ntype IPRangeAggregation struct {\n\tfield           string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\tkeyed           *bool\n\tentries         []IPRangeAggregationEntry\n}\n\ntype IPRangeAggregationEntry struct {\n\tKey  string\n\tMask string\n\tFrom string\n\tTo   string\n}\n\nfunc NewIPRangeAggregation() *IPRangeAggregation {\n\treturn &IPRangeAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t\tentries:         make([]IPRangeAggregationEntry, 0),\n\t}\n}\n\nfunc (a *IPRangeAggregation) Field(field string) *IPRangeAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) SubAggregation(name string, subAggregation Aggregation) *IPRangeAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *IPRangeAggregation) Meta(metaData map[string]interface{}) *IPRangeAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) Keyed(keyed bool) *IPRangeAggregation {\n\ta.keyed = &keyed\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) AddMaskRange(mask string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{Mask: mask})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) AddMaskRangeWithKey(key, mask string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{Key: key, Mask: mask})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) AddRange(from, to string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{From: from, To: to})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) AddRangeWithKey(key, from, to string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{Key: key, From: from, To: to})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) AddUnboundedTo(from string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{From: from, To: \"\"})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) AddUnboundedToWithKey(key, from string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{Key: key, From: from, To: \"\"})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) AddUnboundedFrom(to string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{From: \"\", To: to})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) AddUnboundedFromWithKey(key, to string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{Key: key, From: \"\", To: to})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) Lt(to string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{From: \"\", To: to})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) LtWithKey(key, to string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{Key: key, From: \"\", To: to})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) Between(from, to string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{From: from, To: to})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) BetweenWithKey(key, from, to string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{Key: key, From: from, To: to})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) Gt(from string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{From: from, To: \"\"})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) GtWithKey(key, from string) *IPRangeAggregation {\n\ta.entries = append(a.entries, IPRangeAggregationEntry{Key: key, From: from, To: \"\"})\n\treturn a\n}\n\nfunc (a *IPRangeAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\" : {\n\t//         \"range\" : {\n\t//             \"ip_range\": {\n\t//                 \"field\": \"ip\",\n\t//                 \"ranges\": [\n\t//                     { \"to\": \"10.0.0.5\" },\n\t//                     { \"from\": \"10.0.0.5\" }\n\t//                 ]\n\t//             }\n\t//         }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the { \"ip_range\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"ip_range\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\n\tif a.keyed != nil {\n\t\topts[\"keyed\"] = *a.keyed\n\t}\n\n\tvar ranges []interface{}\n\tfor _, ent := range a.entries {\n\t\tr := make(map[string]interface{})\n\t\tif ent.Key != \"\" {\n\t\t\tr[\"key\"] = ent.Key\n\t\t}\n\t\tif ent.Mask != \"\" {\n\t\t\tr[\"mask\"] = ent.Mask\n\t\t} else {\n\t\t\tif ent.From != \"\" {\n\t\t\t\tr[\"from\"] = ent.From\n\t\t\t}\n\t\t\tif ent.To != \"\" {\n\t\t\t\tr[\"to\"] = ent.To\n\t\t\t}\n\t\t}\n\t\tranges = append(ranges, r)\n\t}\n\topts[\"ranges\"] = ranges\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_ip_range_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestIPRangeAggregation(t *testing.T) {\n\tagg := NewIPRangeAggregation().Field(\"remote_ip\")\n\tagg = agg.AddRange(\"\", \"10.0.0.0\")\n\tagg = agg.AddRange(\"10.1.0.0\", \"10.1.255.255\")\n\tagg = agg.AddRange(\"10.2.0.0\", \"\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"ip_range\":{\"field\":\"remote_ip\",\"ranges\":[{\"to\":\"10.0.0.0\"},{\"from\":\"10.1.0.0\",\"to\":\"10.1.255.255\"},{\"from\":\"10.2.0.0\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestIPRangeAggregationMask(t *testing.T) {\n\tagg := NewIPRangeAggregation().Field(\"remote_ip\")\n\tagg = agg.AddMaskRange(\"10.0.0.0/25\")\n\tagg = agg.AddMaskRange(\"10.0.0.127/25\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"ip_range\":{\"field\":\"remote_ip\",\"ranges\":[{\"mask\":\"10.0.0.0/25\"},{\"mask\":\"10.0.0.127/25\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestIPRangeAggregationWithKeyedFlag(t *testing.T) {\n\tagg := NewIPRangeAggregation().Field(\"remote_ip\")\n\tagg = agg.Keyed(true)\n\tagg = agg.AddRange(\"\", \"10.0.0.0\")\n\tagg = agg.AddRange(\"10.1.0.0\", \"10.1.255.255\")\n\tagg = agg.AddRange(\"10.2.0.0\", \"\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"ip_range\":{\"field\":\"remote_ip\",\"keyed\":true,\"ranges\":[{\"to\":\"10.0.0.0\"},{\"from\":\"10.1.0.0\",\"to\":\"10.1.255.255\"},{\"from\":\"10.2.0.0\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestIPRangeAggregationWithKeys(t *testing.T) {\n\tagg := NewIPRangeAggregation().Field(\"remote_ip\")\n\tagg = agg.Keyed(true)\n\tagg = agg.LtWithKey(\"infinity\", \"10.0.0.5\")\n\tagg = agg.GtWithKey(\"and-beyond\", \"10.0.0.5\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"ip_range\":{\"field\":\"remote_ip\",\"keyed\":true,\"ranges\":[{\"key\":\"infinity\",\"to\":\"10.0.0.5\"},{\"from\":\"10.0.0.5\",\"key\":\"and-beyond\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_missing.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MissingAggregation is a field data based single bucket aggregation,\n// that creates a bucket of all documents in the current document set context\n// that are missing a field value (effectively, missing a field or having\n// the configured NULL value set). This aggregator will often be used in\n// conjunction with other field data bucket aggregators (such as ranges)\n// to return information for all the documents that could not be placed\n// in any of the other buckets due to missing field data values.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-missing-aggregation.html\ntype MissingAggregation struct {\n\tfield           string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewMissingAggregation() *MissingAggregation {\n\treturn &MissingAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *MissingAggregation) Field(field string) *MissingAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *MissingAggregation) SubAggregation(name string, subAggregation Aggregation) *MissingAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MissingAggregation) Meta(metaData map[string]interface{}) *MissingAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *MissingAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"products_without_a_price\" : {\n\t//        \"missing\" : { \"field\" : \"price\" }\n\t//      }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"missing\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"missing\"] = opts\n\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_missing_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMissingAggregation(t *testing.T) {\n\tagg := NewMissingAggregation().Field(\"price\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"missing\":{\"field\":\"price\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMissingAggregationWithMetaData(t *testing.T) {\n\tagg := NewMissingAggregation().Field(\"price\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"missing\":{\"field\":\"price\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_multi_terms.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MultiTermsAggregation is a multi-bucket value source based aggregation\n// where buckets are dynamically built - one per unique set of values.\n// The multi terms aggregation is very similar to the terms aggregation,\n// however in most cases it will be slower than the terms aggregation and will\n// consume more memory. Therefore, if the same set of fields is constantly\n// used, it would be more efficient to index a combined key for this fields\n// as a separate field and use the terms aggregation on this field.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-aggregations-bucket-multi-terms-aggregation.html\ntype MultiTermsAggregation struct {\n\tmultiTerms      []MultiTerm\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\n\tsize                  *int\n\tshardSize             *int\n\tminDocCount           *int\n\tshardMinDocCount      *int\n\tcollectionMode        string\n\tshowTermDocCountError *bool\n\torder                 []MultiTermsOrder\n}\n\n// NewMultiTermsAggregation initializes a new MultiTermsAggregation.\nfunc NewMultiTermsAggregation() *MultiTermsAggregation {\n\treturn &MultiTermsAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\n// Terms adds a slice of field names to return in the aggregation.\n//\n// Notice that it appends to existing terms, so you can use Terms more than\n// once, and mix with MultiTerms method.\nfunc (a *MultiTermsAggregation) Terms(fields ...string) *MultiTermsAggregation {\n\tfor _, field := range fields {\n\t\ta.multiTerms = append(a.multiTerms, MultiTerm{Field: field})\n\t}\n\treturn a\n}\n\n// MultiTerms adds a slice of MultiTerm instances to return in the aggregation.\n//\n// Notice that it appends to existing terms, so you can use MultiTerms more\n// than once, and mix with Terms method.\nfunc (a *MultiTermsAggregation) MultiTerms(multiTerms ...MultiTerm) *MultiTermsAggregation {\n\ta.multiTerms = append(a.multiTerms, multiTerms...)\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) SubAggregation(name string, subAggregation Aggregation) *MultiTermsAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MultiTermsAggregation) Meta(metaData map[string]interface{}) *MultiTermsAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) Size(size int) *MultiTermsAggregation {\n\ta.size = &size\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) ShardSize(shardSize int) *MultiTermsAggregation {\n\ta.shardSize = &shardSize\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) MinDocCount(minDocCount int) *MultiTermsAggregation {\n\ta.minDocCount = &minDocCount\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) ShardMinDocCount(shardMinDocCount int) *MultiTermsAggregation {\n\ta.shardMinDocCount = &shardMinDocCount\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) Order(order string, asc bool) *MultiTermsAggregation {\n\ta.order = append(a.order, MultiTermsOrder{Field: order, Ascending: asc})\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) OrderByCount(asc bool) *MultiTermsAggregation {\n\t// \"order\" : { \"_count\" : \"asc\" }\n\ta.order = append(a.order, MultiTermsOrder{Field: \"_count\", Ascending: asc})\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) OrderByCountAsc() *MultiTermsAggregation {\n\treturn a.OrderByCount(true)\n}\n\nfunc (a *MultiTermsAggregation) OrderByCountDesc() *MultiTermsAggregation {\n\treturn a.OrderByCount(false)\n}\n\nfunc (a *MultiTermsAggregation) OrderByKey(asc bool) *MultiTermsAggregation {\n\t// \"order\" : { \"_term\" : \"asc\" }\n\ta.order = append(a.order, MultiTermsOrder{Field: \"_key\", Ascending: asc})\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) OrderByKeyAsc() *MultiTermsAggregation {\n\treturn a.OrderByKey(true)\n}\n\nfunc (a *MultiTermsAggregation) OrderByKeyDesc() *MultiTermsAggregation {\n\treturn a.OrderByKey(false)\n}\n\n// OrderByAggregation creates a bucket ordering strategy which sorts buckets\n// based on a single-valued calc get.\nfunc (a *MultiTermsAggregation) OrderByAggregation(aggName string, asc bool) *MultiTermsAggregation {\n\t// {\n\t// \t\"aggs\": {\n\t// \t  \"genres_and_products\": {\n\t// \t\t\"multi_terms\": {\n\t// \t\t  \"terms\": [\n\t// \t\t\t{\n\t// \t\t\t  \"field\": \"genre\"\n\t// \t\t\t},\n\t// \t\t\t{\n\t// \t\t\t  \"field\": \"product\"\n\t// \t\t\t}\n\t// \t\t  ],\n\t// \t\t  \"order\": {\n\t// \t\t\t\"total_quantity\": \"desc\"\n\t// \t\t  }\n\t// \t\t},\n\t// \t\t\"aggs\": {\n\t// \t\t  \"total_quantity\": {\n\t// \t\t\t\"sum\": {\n\t// \t\t\t  \"field\": \"quantity\"\n\t// \t\t\t}\n\t// \t\t  }\n\t// \t\t}\n\t// \t  }\n\t// \t}\n\t// }\n\ta.order = append(a.order, MultiTermsOrder{Field: aggName, Ascending: asc})\n\treturn a\n}\n\n// OrderByAggregationAndMetric creates a bucket ordering strategy which\n// sorts buckets based on a multi-valued calc get.\nfunc (a *MultiTermsAggregation) OrderByAggregationAndMetric(aggName, metric string, asc bool) *MultiTermsAggregation {\n\t// {\n\t// \t\"aggs\": {\n\t// \t  \"genres_and_products\": {\n\t// \t\t\"multi_terms\": {\n\t// \t\t  \"terms\": [\n\t// \t\t\t{\n\t// \t\t\t  \"field\": \"genre\"\n\t// \t\t\t},\n\t// \t\t\t{\n\t// \t\t\t  \"field\": \"product\"\n\t// \t\t\t}\n\t// \t\t  ],\n\t// \t\t  \"order\": {\n\t// \t\t\t\"total_quantity\": \"desc\"\n\t// \t\t  }\n\t// \t\t},\n\t// \t\t\"aggs\": {\n\t// \t\t  \"total_quantity\": {\n\t// \t\t\t\"sum\": {\n\t// \t\t\t  \"field\": \"quantity\"\n\t// \t\t\t}\n\t// \t\t  }\n\t// \t\t}\n\t// \t  }\n\t// \t}\n\t// }\n\ta.order = append(a.order, MultiTermsOrder{Field: aggName + \".\" + metric, Ascending: asc})\n\treturn a\n}\n\n// Collection mode can be depth_first or breadth_first as of 1.4.0.\nfunc (a *MultiTermsAggregation) CollectionMode(collectionMode string) *MultiTermsAggregation {\n\ta.collectionMode = collectionMode\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) ShowTermDocCountError(showTermDocCountError bool) *MultiTermsAggregation {\n\ta.showTermDocCountError = &showTermDocCountError\n\treturn a\n}\n\nfunc (a *MultiTermsAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t// \t\"aggs\": {\n\t// \t  \"genres_and_products\": {\n\t// \t\t\"multi_terms\": {\n\t// \t\t  \"terms\": [\n\t// \t\t\t{\n\t// \t\t\t  \"field\": \"genre\"\n\t// \t\t\t},\n\t// \t\t\t{\n\t// \t\t\t  \"field\": \"product\"\n\t// \t\t\t}\n\t// \t\t  ]\n\t// \t\t}\n\t// \t  }\n\t// \t}\n\t// }\n\t// This method returns only the \"multi_terms\": { \"terms\": [ { \"field\": \"genre\" }, { \"field\": \"product\" } ] } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"multi_terms\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tterms := make([]interface{}, len(a.multiTerms))\n\tfor i := range a.multiTerms {\n\t\ts, err := a.multiTerms[i].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tterms[i] = s\n\t}\n\topts[\"terms\"] = terms\n\n\t// TermsBuilder\n\tif a.size != nil && *a.size >= 0 {\n\t\topts[\"size\"] = *a.size\n\t}\n\tif a.shardSize != nil && *a.shardSize >= 0 {\n\t\topts[\"shard_size\"] = *a.shardSize\n\t}\n\tif a.minDocCount != nil && *a.minDocCount >= 0 {\n\t\topts[\"min_doc_count\"] = *a.minDocCount\n\t}\n\tif a.shardMinDocCount != nil && *a.shardMinDocCount >= 0 {\n\t\topts[\"shard_min_doc_count\"] = *a.shardMinDocCount\n\t}\n\tif a.showTermDocCountError != nil {\n\t\topts[\"show_term_doc_count_error\"] = *a.showTermDocCountError\n\t}\n\tif a.collectionMode != \"\" {\n\t\topts[\"collect_mode\"] = a.collectionMode\n\t}\n\tif len(a.order) > 0 {\n\t\tvar orderSlice []interface{}\n\t\tfor _, order := range a.order {\n\t\t\tsrc, err := order.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\torderSlice = append(orderSlice, src)\n\t\t}\n\t\topts[\"order\"] = orderSlice\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n\n// MultiTermsOrder specifies a single order field for a multi terms aggregation.\ntype MultiTermsOrder struct {\n\tField     string\n\tAscending bool\n}\n\n// Source returns serializable JSON of the MultiTermsOrder.\nfunc (order *MultiTermsOrder) Source() (interface{}, error) {\n\tsource := make(map[string]string)\n\tif order.Ascending {\n\t\tsource[order.Field] = \"asc\"\n\t} else {\n\t\tsource[order.Field] = \"desc\"\n\t}\n\treturn source, nil\n}\n\n// MultiTerm specifies a single term field for a multi terms aggregation.\ntype MultiTerm struct {\n\tField   string\n\tMissing interface{}\n}\n\n// Source returns serializable JSON of the MultiTerm.\nfunc (term *MultiTerm) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tsource[\"field\"] = term.Field\n\tif term.Missing != nil {\n\t\tsource[\"missing\"] = term.Missing\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_multi_terms_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMultiTermsAggregation(t *testing.T) {\n\tagg := NewMultiTermsAggregation().Terms(\"genre\", \"product\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_terms\":{\"terms\":[{\"field\":\"genre\"},{\"field\":\"product\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiTermsAggregationWithMultiTerms(t *testing.T) {\n\tagg := NewMultiTermsAggregation().MultiTerms(\n\t\tMultiTerm{Field: \"genre\", Missing: \"n/a\"},\n\t\tMultiTerm{Field: \"product\", Missing: \"n/a\"},\n\t)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_terms\":{\"terms\":[{\"field\":\"genre\",\"missing\":\"n/a\"},{\"field\":\"product\",\"missing\":\"n/a\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiTermsAggregationWithSubAggregation(t *testing.T) {\n\tsubAgg := NewAvgAggregation().Field(\"height\")\n\tagg := NewMultiTermsAggregation().Terms(\"genre\", \"product\").Size(10).\n\t\tOrderByAggregation(\"avg_height\", false)\n\tagg = agg.SubAggregation(\"avg_height\", subAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"avg_height\":{\"avg\":{\"field\":\"height\"}}},\"multi_terms\":{\"order\":[{\"avg_height\":\"desc\"}],\"size\":10,\"terms\":[{\"field\":\"genre\"},{\"field\":\"product\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiTermsAggregationWithMultipleSubAggregation(t *testing.T) {\n\tsubAgg1 := NewAvgAggregation().Field(\"height\")\n\tsubAgg2 := NewAvgAggregation().Field(\"width\")\n\tagg := NewMultiTermsAggregation().Terms(\"genre\", \"product\").Size(10).\n\t\tOrderByAggregation(\"avg_height\", false)\n\tagg = agg.SubAggregation(\"avg_height\", subAgg1)\n\tagg = agg.SubAggregation(\"avg_width\", subAgg2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"avg_height\":{\"avg\":{\"field\":\"height\"}},\"avg_width\":{\"avg\":{\"field\":\"width\"}}},\"multi_terms\":{\"order\":[{\"avg_height\":\"desc\"}],\"size\":10,\"terms\":[{\"field\":\"genre\"},{\"field\":\"product\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiTermsAggregationWithMetaData(t *testing.T) {\n\tagg := NewMultiTermsAggregation().Terms(\"genre\", \"product\").Size(10).OrderByKeyDesc()\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"multi_terms\":{\"order\":[{\"_key\":\"desc\"}],\"size\":10,\"terms\":[{\"field\":\"genre\"},{\"field\":\"product\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiTermsAggregationWithMissing(t *testing.T) {\n\tagg := NewMultiTermsAggregation().MultiTerms(\n\t\tMultiTerm{Field: \"genre\"},\n\t\tMultiTerm{Field: \"product\", Missing: \"n/a\"},\n\t).Size(10)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_terms\":{\"size\":10,\"terms\":[{\"field\":\"genre\"},{\"field\":\"product\",\"missing\":\"n/a\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_nested.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// NestedAggregation is a special single bucket aggregation that enables\n// aggregating nested documents.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-nested-aggregation.html\ntype NestedAggregation struct {\n\tpath            string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewNestedAggregation() *NestedAggregation {\n\treturn &NestedAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *NestedAggregation) SubAggregation(name string, subAggregation Aggregation) *NestedAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *NestedAggregation) Meta(metaData map[string]interface{}) *NestedAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *NestedAggregation) Path(path string) *NestedAggregation {\n\ta.path = path\n\treturn a\n}\n\nfunc (a *NestedAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//     \"query\" : {\n\t//         \"match\" : { \"name\" : \"led tv\" }\n\t//     }\n\t//     \"aggs\" : {\n\t//         \"resellers\" : {\n\t//             \"nested\" : {\n\t//                 \"path\" : \"resellers\"\n\t//             },\n\t//             \"aggs\" : {\n\t//                 \"min_price\" : { \"min\" : { \"field\" : \"resellers.price\" } }\n\t//             }\n\t//         }\n\t//     }\n\t//\t}\n\t// This method returns only the { \"nested\" : {} } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"nested\"] = opts\n\n\topts[\"path\"] = a.path\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_nested_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestNestedAggregation(t *testing.T) {\n\tagg := NewNestedAggregation().Path(\"resellers\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"nested\":{\"path\":\"resellers\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestNestedAggregationWithSubAggregation(t *testing.T) {\n\tminPriceAgg := NewMinAggregation().Field(\"resellers.price\")\n\tagg := NewNestedAggregation().Path(\"resellers\").SubAggregation(\"min_price\", minPriceAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"min_price\":{\"min\":{\"field\":\"resellers.price\"}}},\"nested\":{\"path\":\"resellers\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestNestedAggregationWithMetaData(t *testing.T) {\n\tagg := NewNestedAggregation().Path(\"resellers\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"nested\":{\"path\":\"resellers\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_range.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"time\"\n)\n\n// RangeAggregation is a multi-bucket value source based aggregation that\n// enables the user to define a set of ranges - each representing a bucket.\n// During the aggregation process, the values extracted from each document\n// will be checked against each bucket range and \"bucket\" the\n// relevant/matching document. Note that this aggregration includes the\n// from value and excludes the to value for each range.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-range-aggregation.html\ntype RangeAggregation struct {\n\tfield           string\n\tscript          *Script\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\tkeyed           *bool\n\tunmapped        *bool\n\tentries         []rangeAggregationEntry\n}\n\ntype rangeAggregationEntry struct {\n\tKey  string\n\tFrom interface{}\n\tTo   interface{}\n}\n\nfunc NewRangeAggregation() *RangeAggregation {\n\treturn &RangeAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t\tentries:         make([]rangeAggregationEntry, 0),\n\t}\n}\n\nfunc (a *RangeAggregation) Field(field string) *RangeAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *RangeAggregation) Script(script *Script) *RangeAggregation {\n\ta.script = script\n\treturn a\n}\n\n// Missing configures the value to use when documents miss a value.\nfunc (a *RangeAggregation) Missing(missing interface{}) *RangeAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *RangeAggregation) SubAggregation(name string, subAggregation Aggregation) *RangeAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *RangeAggregation) Meta(metaData map[string]interface{}) *RangeAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *RangeAggregation) Keyed(keyed bool) *RangeAggregation {\n\ta.keyed = &keyed\n\treturn a\n}\n\nfunc (a *RangeAggregation) Unmapped(unmapped bool) *RangeAggregation {\n\ta.unmapped = &unmapped\n\treturn a\n}\n\nfunc (a *RangeAggregation) AddRange(from, to interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{From: from, To: to})\n\treturn a\n}\n\nfunc (a *RangeAggregation) AddRangeWithKey(key string, from, to interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{Key: key, From: from, To: to})\n\treturn a\n}\n\nfunc (a *RangeAggregation) AddUnboundedTo(from interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{From: from, To: nil})\n\treturn a\n}\n\nfunc (a *RangeAggregation) AddUnboundedToWithKey(key string, from interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{Key: key, From: from, To: nil})\n\treturn a\n}\n\nfunc (a *RangeAggregation) AddUnboundedFrom(to interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{From: nil, To: to})\n\treturn a\n}\n\nfunc (a *RangeAggregation) AddUnboundedFromWithKey(key string, to interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{Key: key, From: nil, To: to})\n\treturn a\n}\n\nfunc (a *RangeAggregation) Lt(to interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{From: nil, To: to})\n\treturn a\n}\n\nfunc (a *RangeAggregation) LtWithKey(key string, to interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{Key: key, From: nil, To: to})\n\treturn a\n}\n\nfunc (a *RangeAggregation) Between(from, to interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{From: from, To: to})\n\treturn a\n}\n\nfunc (a *RangeAggregation) BetweenWithKey(key string, from, to interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{Key: key, From: from, To: to})\n\treturn a\n}\n\nfunc (a *RangeAggregation) Gt(from interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{From: from, To: nil})\n\treturn a\n}\n\nfunc (a *RangeAggregation) GtWithKey(key string, from interface{}) *RangeAggregation {\n\ta.entries = append(a.entries, rangeAggregationEntry{Key: key, From: from, To: nil})\n\treturn a\n}\n\nfunc (a *RangeAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\" : {\n\t//         \"price_ranges\" : {\n\t//             \"range\" : {\n\t//                 \"field\" : \"price\",\n\t//                 \"ranges\" : [\n\t//                     { \"to\" : 50 },\n\t//                     { \"from\" : 50, \"to\" : 100 },\n\t//                     { \"from\" : 100 }\n\t//                 ]\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the { \"range\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"range\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\tif a.keyed != nil {\n\t\topts[\"keyed\"] = *a.keyed\n\t}\n\tif a.unmapped != nil {\n\t\topts[\"unmapped\"] = *a.unmapped\n\t}\n\n\tvar ranges []interface{}\n\tfor _, ent := range a.entries {\n\t\tr := make(map[string]interface{})\n\t\tif ent.Key != \"\" {\n\t\t\tr[\"key\"] = ent.Key\n\t\t}\n\t\tif ent.From != nil {\n\t\t\tswitch from := ent.From.(type) {\n\t\t\tcase int, int16, int32, int64, float32, float64:\n\t\t\t\tr[\"from\"] = from\n\t\t\tcase *int, *int16, *int32, *int64, *float32, *float64:\n\t\t\t\tr[\"from\"] = from\n\t\t\tcase time.Time:\n\t\t\t\tr[\"from\"] = from.Format(time.RFC3339)\n\t\t\tcase *time.Time:\n\t\t\t\tr[\"from\"] = from.Format(time.RFC3339)\n\t\t\tcase string:\n\t\t\t\tr[\"from\"] = from\n\t\t\tcase *string:\n\t\t\t\tr[\"from\"] = from\n\t\t\t}\n\t\t}\n\t\tif ent.To != nil {\n\t\t\tswitch to := ent.To.(type) {\n\t\t\tcase int, int16, int32, int64, float32, float64:\n\t\t\t\tr[\"to\"] = to\n\t\t\tcase *int, *int16, *int32, *int64, *float32, *float64:\n\t\t\t\tr[\"to\"] = to\n\t\t\tcase time.Time:\n\t\t\t\tr[\"to\"] = to.Format(time.RFC3339)\n\t\t\tcase *time.Time:\n\t\t\t\tr[\"to\"] = to.Format(time.RFC3339)\n\t\t\tcase string:\n\t\t\t\tr[\"to\"] = to\n\t\t\tcase *string:\n\t\t\t\tr[\"to\"] = to\n\t\t\t}\n\t\t}\n\t\tranges = append(ranges, r)\n\t}\n\topts[\"ranges\"] = ranges\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_range_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestRangeAggregation(t *testing.T) {\n\tagg := NewRangeAggregation().Field(\"price\")\n\tagg = agg.AddRange(nil, 50)\n\tagg = agg.AddRange(50, 100)\n\tagg = agg.AddRange(100, nil)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"field\":\"price\",\"ranges\":[{\"to\":50},{\"from\":50,\"to\":100},{\"from\":100}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRangeAggregationWithPointers(t *testing.T) {\n\tfifty := 50\n\thundred := 100\n\tagg := NewRangeAggregation().Field(\"price\")\n\tagg = agg.AddRange(nil, &fifty)\n\tagg = agg.AddRange(fifty, &hundred)\n\tagg = agg.AddRange(hundred, nil)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"field\":\"price\",\"ranges\":[{\"to\":50},{\"from\":50,\"to\":100},{\"from\":100}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRangeAggregationWithUnbounded(t *testing.T) {\n\tagg := NewRangeAggregation().Field(\"field_name\").\n\t\tAddUnboundedFrom(50).\n\t\tAddRange(20, 70).\n\t\tAddRange(70, 120).\n\t\tAddUnboundedTo(150)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"field\":\"field_name\",\"ranges\":[{\"to\":50},{\"from\":20,\"to\":70},{\"from\":70,\"to\":120},{\"from\":150}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRangeAggregationWithLtAndCo(t *testing.T) {\n\tagg := NewRangeAggregation().Field(\"field_name\").\n\t\tLt(50).\n\t\tBetween(20, 70).\n\t\tBetween(70, 120).\n\t\tGt(150)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"field\":\"field_name\",\"ranges\":[{\"to\":50},{\"from\":20,\"to\":70},{\"from\":70,\"to\":120},{\"from\":150}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRangeAggregationWithKeyedFlag(t *testing.T) {\n\tagg := NewRangeAggregation().Field(\"field_name\").\n\t\tKeyed(true).\n\t\tLt(50).\n\t\tBetween(20, 70).\n\t\tBetween(70, 120).\n\t\tGt(150)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"field\":\"field_name\",\"keyed\":true,\"ranges\":[{\"to\":50},{\"from\":20,\"to\":70},{\"from\":70,\"to\":120},{\"from\":150}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRangeAggregationWithKeys(t *testing.T) {\n\tagg := NewRangeAggregation().Field(\"field_name\").\n\t\tKeyed(true).\n\t\tLtWithKey(\"cheap\", 50).\n\t\tBetweenWithKey(\"affordable\", 20, 70).\n\t\tBetweenWithKey(\"average\", 70, 120).\n\t\tGtWithKey(\"expensive\", 150)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"field\":\"field_name\",\"keyed\":true,\"ranges\":[{\"key\":\"cheap\",\"to\":50},{\"from\":20,\"key\":\"affordable\",\"to\":70},{\"from\":70,\"key\":\"average\",\"to\":120},{\"from\":150,\"key\":\"expensive\"}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRangeAggregationWithMetaData(t *testing.T) {\n\tagg := NewRangeAggregation().Field(\"price\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tagg = agg.AddRange(nil, 50)\n\tagg = agg.AddRange(50, 100)\n\tagg = agg.AddRange(100, nil)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"range\":{\"field\":\"price\",\"ranges\":[{\"to\":50},{\"from\":50,\"to\":100},{\"from\":100}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRangeAggregationWithMissing(t *testing.T) {\n\tagg := NewRangeAggregation().Field(\"price\").Missing(0)\n\tagg = agg.AddRange(nil, 50)\n\tagg = agg.AddRange(50, 100)\n\tagg = agg.AddRange(100, nil)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"field\":\"price\",\"missing\":0,\"ranges\":[{\"to\":50},{\"from\":50,\"to\":100},{\"from\":100}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_rare_terms.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// RareTermsAggregation is a multi-bucket value source based aggregation\n// which finds \"rare\" terms — terms that are at the long-tail of the distribution\n// and are not frequent. Conceptually, this is like a terms aggregation that\n// is sorted by _count ascending.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-rare-terms-aggregation.html\n// for details.\ntype RareTermsAggregation struct {\n\tfield           string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\n\tincludeExclude *TermsAggregationIncludeExclude\n\tmaxDocCount    *int\n\tprecision      *float64\n\tmissing        interface{}\n}\n\nfunc NewRareTermsAggregation() *RareTermsAggregation {\n\treturn &RareTermsAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *RareTermsAggregation) Field(field string) *RareTermsAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) SubAggregation(name string, subAggregation Aggregation) *RareTermsAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *RareTermsAggregation) Meta(metaData map[string]interface{}) *RareTermsAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) MaxDocCount(maxDocCount int) *RareTermsAggregation {\n\ta.maxDocCount = &maxDocCount\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) Precision(precision float64) *RareTermsAggregation {\n\ta.precision = &precision\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) Missing(missing interface{}) *RareTermsAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) Include(regexp string) *RareTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Include = regexp\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) IncludeValues(values ...interface{}) *RareTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.IncludeValues = append(a.includeExclude.IncludeValues, values...)\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) Exclude(regexp string) *RareTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Exclude = regexp\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) ExcludeValues(values ...interface{}) *RareTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.ExcludeValues = append(a.includeExclude.ExcludeValues, values...)\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) IncludeExclude(includeExclude *TermsAggregationIncludeExclude) *RareTermsAggregation {\n\ta.includeExclude = includeExclude\n\treturn a\n}\n\nfunc (a *RareTermsAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggregations\" : {\n\t//         \"genres\" : {\n\t//             \"rare_terms\" : { \"field\" : \"genre\" }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the\n\t//   \"rare_terms\" : { \"field\" : \"genre\" }\n\t// part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"rare_terms\"] = opts\n\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.maxDocCount != nil {\n\t\topts[\"max_doc_count\"] = *a.maxDocCount\n\t}\n\tif a.precision != nil {\n\t\topts[\"precision\"] = *a.precision\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\t// Include/Exclude\n\tif ie := a.includeExclude; ie != nil {\n\t\tif err := ie.MergeInto(opts); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_rare_terms_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestRareTermsAggregation(t *testing.T) {\n\tagg := NewRareTermsAggregation().Field(\"genre\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"rare_terms\":{\"field\":\"genre\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRareTermsAggregationWithArgs(t *testing.T) {\n\tagg := NewRareTermsAggregation().\n\t\tField(\"genre\").\n\t\tMaxDocCount(2).\n\t\tPrecision(0.1).\n\t\tMissing(\"n/a\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"rare_terms\":{\"field\":\"genre\",\"max_doc_count\":2,\"missing\":\"n/a\",\"precision\":0.1}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRareTermsAggregationWithIncludeExclude(t *testing.T) {\n\tagg := NewRareTermsAggregation().Field(\"genre\").Include(\"swi*\").Exclude(\"electro*\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"rare_terms\":{\"exclude\":\"electro*\",\"field\":\"genre\",\"include\":\"swi*\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRareTermsAggregationWithIncludeExcludeValues(t *testing.T) {\n\tagg := NewRareTermsAggregation().Field(\"genre\").IncludeValues(\"swing\", \"rock\").ExcludeValues(\"jazz\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"rare_terms\":{\"exclude\":[\"jazz\"],\"field\":\"genre\",\"include\":[\"swing\",\"rock\"]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRareTermsAggregationSubAggregation(t *testing.T) {\n\tgenres := NewRareTermsAggregation().Field(\"genre\")\n\tagg := NewTermsAggregation().Field(\"force\")\n\tagg = agg.SubAggregation(\"genres\", genres)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"genres\":{\"rare_terms\":{\"field\":\"genre\"}}},\"terms\":{\"field\":\"force\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRareTermsAggregationWithMetaData(t *testing.T) {\n\tagg := NewRareTermsAggregation().Field(\"genre\")\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"rare_terms\":{\"field\":\"genre\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_reverse_nested.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// ReverseNestedAggregation defines a special single bucket aggregation\n// that enables aggregating on parent docs from nested documents.\n// Effectively this aggregation can break out of the nested block\n// structure and link to other nested structures or the root document,\n// which allows nesting other aggregations that aren’t part of\n// the nested object in a nested aggregation.\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-reverse-nested-aggregation.html\ntype ReverseNestedAggregation struct {\n\tpath            string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\n// NewReverseNestedAggregation initializes a new ReverseNestedAggregation\n// bucket aggregation.\nfunc NewReverseNestedAggregation() *ReverseNestedAggregation {\n\treturn &ReverseNestedAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\n// Path set the path to use for this nested aggregation. The path must match\n// the path to a nested object in the mappings. If it is not specified\n// then this aggregation will go back to the root document.\nfunc (a *ReverseNestedAggregation) Path(path string) *ReverseNestedAggregation {\n\ta.path = path\n\treturn a\n}\n\nfunc (a *ReverseNestedAggregation) SubAggregation(name string, subAggregation Aggregation) *ReverseNestedAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *ReverseNestedAggregation) Meta(metaData map[string]interface{}) *ReverseNestedAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *ReverseNestedAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"reverse_nested\" : {\n\t//        \"path\": \"...\"\n\t//      }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"reverse_nested\" : {} } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"reverse_nested\"] = opts\n\n\tif a.path != \"\" {\n\t\topts[\"path\"] = a.path\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_reverse_nested_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestReverseNestedAggregation(t *testing.T) {\n\tagg := NewReverseNestedAggregation()\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"reverse_nested\":{}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestReverseNestedAggregationWithPath(t *testing.T) {\n\tagg := NewReverseNestedAggregation().Path(\"comments\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"reverse_nested\":{\"path\":\"comments\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestReverseNestedAggregationWithSubAggregation(t *testing.T) {\n\tavgPriceAgg := NewAvgAggregation().Field(\"price\")\n\tagg := NewReverseNestedAggregation().\n\t\tPath(\"a_path\").\n\t\tSubAggregation(\"avg_price\", avgPriceAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"avg_price\":{\"avg\":{\"field\":\"price\"}}},\"reverse_nested\":{\"path\":\"a_path\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestReverseNestedAggregationWithMeta(t *testing.T) {\n\tagg := NewReverseNestedAggregation().\n\t\tPath(\"a_path\").\n\t\tMeta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"reverse_nested\":{\"path\":\"a_path\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_sampler.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SamplerAggregation is a filtering aggregation used to limit any\n// sub aggregations' processing to a sample of the top-scoring documents.\n// Optionally, diversity settings can be used to limit the number of matches\n// that share a common value such as an \"author\".\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-sampler-aggregation.html\ntype SamplerAggregation struct {\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\n\tshardSize int\n}\n\nfunc NewSamplerAggregation() *SamplerAggregation {\n\treturn &SamplerAggregation{\n\t\tshardSize:       -1,\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *SamplerAggregation) SubAggregation(name string, subAggregation Aggregation) *SamplerAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *SamplerAggregation) Meta(metaData map[string]interface{}) *SamplerAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// ShardSize sets the maximum number of docs returned from each shard.\nfunc (a *SamplerAggregation) ShardSize(shardSize int) *SamplerAggregation {\n\ta.shardSize = shardSize\n\treturn a\n}\n\nfunc (a *SamplerAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"aggs\" : {\n\t//         \"sample\" : {\n\t//             \"sampler\" : {\n\t//                 \"shard_size\" : 200\n\t//             },\n\t// \t\t\t\t\t\t \"aggs\": {\n\t//                 \"keywords\": {\n\t//                     \"significant_terms\": {\n\t//                         \"field\": \"text\"\n\t//                      }\n\t//                 }\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the { \"sampler\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"sampler\"] = opts\n\n\tif a.shardSize >= 0 {\n\t\topts[\"shard_size\"] = a.shardSize\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_sampler_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSamplerAggregation(t *testing.T) {\n\tkeywordsAgg := NewSignificantTermsAggregation().Field(\"text\")\n\tagg := NewSamplerAggregation().\n\t\tShardSize(200).\n\t\tSubAggregation(\"keywords\", keywordsAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"keywords\":{\"significant_terms\":{\"field\":\"text\"}}},\"sampler\":{\"shard_size\":200}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_significant_terms.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SignificantTermsAggregation is an aggregation that returns interesting\n// or unusual occurrences of terms in a set.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html\ntype SignificantTermsAggregation struct {\n\tfield           string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\n\tminDocCount           *int\n\tshardMinDocCount      *int\n\trequiredSize          *int\n\tshardSize             *int\n\tfilter                Query\n\texecutionHint         string\n\tsignificanceHeuristic SignificanceHeuristic\n\tincludeExclude        *TermsAggregationIncludeExclude\n}\n\nfunc NewSignificantTermsAggregation() *SignificantTermsAggregation {\n\treturn &SignificantTermsAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *SignificantTermsAggregation) Field(field string) *SignificantTermsAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) SubAggregation(name string, subAggregation Aggregation) *SignificantTermsAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *SignificantTermsAggregation) Meta(metaData map[string]interface{}) *SignificantTermsAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) MinDocCount(minDocCount int) *SignificantTermsAggregation {\n\ta.minDocCount = &minDocCount\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) ShardMinDocCount(shardMinDocCount int) *SignificantTermsAggregation {\n\ta.shardMinDocCount = &shardMinDocCount\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) RequiredSize(requiredSize int) *SignificantTermsAggregation {\n\ta.requiredSize = &requiredSize\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) ShardSize(shardSize int) *SignificantTermsAggregation {\n\ta.shardSize = &shardSize\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) BackgroundFilter(filter Query) *SignificantTermsAggregation {\n\ta.filter = filter\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) ExecutionHint(hint string) *SignificantTermsAggregation {\n\ta.executionHint = hint\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) SignificanceHeuristic(heuristic SignificanceHeuristic) *SignificantTermsAggregation {\n\ta.significanceHeuristic = heuristic\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) Include(regexp string) *SignificantTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Include = regexp\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) IncludeValues(values ...interface{}) *SignificantTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.IncludeValues = append(a.includeExclude.IncludeValues, values...)\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) Exclude(regexp string) *SignificantTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Exclude = regexp\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) ExcludeValues(values ...interface{}) *SignificantTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.ExcludeValues = append(a.includeExclude.ExcludeValues, values...)\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) Partition(p int) *SignificantTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Partition = p\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) NumPartitions(n int) *SignificantTermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.NumPartitions = n\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) IncludeExclude(includeExclude *TermsAggregationIncludeExclude) *SignificantTermsAggregation {\n\ta.includeExclude = includeExclude\n\treturn a\n}\n\nfunc (a *SignificantTermsAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"query\" : {\n\t//         \"terms\" : {\"force\" : [ \"British Transport Police\" ]}\n\t//     },\n\t//     \"aggregations\" : {\n\t//         \"significantCrimeTypes\" : {\n\t//             \"significant_terms\" : { \"field\" : \"crime_type\" }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the\n\t//   { \"significant_terms\" : { \"field\" : \"crime_type\" }\n\t// part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"significant_terms\"] = opts\n\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.requiredSize != nil {\n\t\topts[\"size\"] = *a.requiredSize // not a typo!\n\t}\n\tif a.shardSize != nil {\n\t\topts[\"shard_size\"] = *a.shardSize\n\t}\n\tif a.minDocCount != nil {\n\t\topts[\"min_doc_count\"] = *a.minDocCount\n\t}\n\tif a.shardMinDocCount != nil {\n\t\topts[\"shard_min_doc_count\"] = *a.shardMinDocCount\n\t}\n\tif a.executionHint != \"\" {\n\t\topts[\"execution_hint\"] = a.executionHint\n\t}\n\tif a.filter != nil {\n\t\tsrc, err := a.filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"background_filter\"] = src\n\t}\n\tif a.significanceHeuristic != nil {\n\t\tname := a.significanceHeuristic.Name()\n\t\tsrc, err := a.significanceHeuristic.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[name] = src\n\t}\n\n\t// Include/Exclude\n\tif ie := a.includeExclude; ie != nil {\n\t\tif err := ie.MergeInto(opts); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n\n// -- Significance heuristics --\n\ntype SignificanceHeuristic interface {\n\tName() string\n\tSource() (interface{}, error)\n}\n\n// -- Chi Square --\n\n// ChiSquareSignificanceHeuristic implements Chi square as described\n// in \"Information Retrieval\", Manning et al., Chapter 13.5.2.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_chi_square\n// for details.\ntype ChiSquareSignificanceHeuristic struct {\n\tbackgroundIsSuperset *bool\n\tincludeNegatives     *bool\n}\n\n// NewChiSquareSignificanceHeuristic initializes a new ChiSquareSignificanceHeuristic.\nfunc NewChiSquareSignificanceHeuristic() *ChiSquareSignificanceHeuristic {\n\treturn &ChiSquareSignificanceHeuristic{}\n}\n\n// Name returns the name of the heuristic in the REST interface.\nfunc (sh *ChiSquareSignificanceHeuristic) Name() string {\n\treturn \"chi_square\"\n}\n\n// BackgroundIsSuperset indicates whether you defined a custom background\n// filter that represents a difference set of documents that you want to\n// compare to.\nfunc (sh *ChiSquareSignificanceHeuristic) BackgroundIsSuperset(backgroundIsSuperset bool) *ChiSquareSignificanceHeuristic {\n\tsh.backgroundIsSuperset = &backgroundIsSuperset\n\treturn sh\n}\n\n// IncludeNegatives indicates whether to filter out the terms that appear\n// much less in the subset than in the background without the subset.\nfunc (sh *ChiSquareSignificanceHeuristic) IncludeNegatives(includeNegatives bool) *ChiSquareSignificanceHeuristic {\n\tsh.includeNegatives = &includeNegatives\n\treturn sh\n}\n\n// Source returns the parameters that need to be added to the REST parameters.\nfunc (sh *ChiSquareSignificanceHeuristic) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif sh.backgroundIsSuperset != nil {\n\t\tsource[\"background_is_superset\"] = *sh.backgroundIsSuperset\n\t}\n\tif sh.includeNegatives != nil {\n\t\tsource[\"include_negatives\"] = *sh.includeNegatives\n\t}\n\treturn source, nil\n}\n\n// -- GND --\n\n// GNDSignificanceHeuristic implements the \"Google Normalized Distance\"\n// as described in \"The Google Similarity Distance\", Cilibrasi and Vitanyi,\n// 2007.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_google_normalized_distance\n// for details.\ntype GNDSignificanceHeuristic struct {\n\tbackgroundIsSuperset *bool\n}\n\n// NewGNDSignificanceHeuristic implements a new GNDSignificanceHeuristic.\nfunc NewGNDSignificanceHeuristic() *GNDSignificanceHeuristic {\n\treturn &GNDSignificanceHeuristic{}\n}\n\n// Name returns the name of the heuristic in the REST interface.\nfunc (sh *GNDSignificanceHeuristic) Name() string {\n\treturn \"gnd\"\n}\n\n// BackgroundIsSuperset indicates whether you defined a custom background\n// filter that represents a difference set of documents that you want to\n// compare to.\nfunc (sh *GNDSignificanceHeuristic) BackgroundIsSuperset(backgroundIsSuperset bool) *GNDSignificanceHeuristic {\n\tsh.backgroundIsSuperset = &backgroundIsSuperset\n\treturn sh\n}\n\n// Source returns the parameters that need to be added to the REST parameters.\nfunc (sh *GNDSignificanceHeuristic) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif sh.backgroundIsSuperset != nil {\n\t\tsource[\"background_is_superset\"] = *sh.backgroundIsSuperset\n\t}\n\treturn source, nil\n}\n\n// -- JLH Score --\n\n// JLHScoreSignificanceHeuristic implements the JLH score as described in\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_jlh_score.\ntype JLHScoreSignificanceHeuristic struct{}\n\n// NewJLHScoreSignificanceHeuristic initializes a new JLHScoreSignificanceHeuristic.\nfunc NewJLHScoreSignificanceHeuristic() *JLHScoreSignificanceHeuristic {\n\treturn &JLHScoreSignificanceHeuristic{}\n}\n\n// Name returns the name of the heuristic in the REST interface.\nfunc (sh *JLHScoreSignificanceHeuristic) Name() string {\n\treturn \"jlh\"\n}\n\n// Source returns the parameters that need to be added to the REST parameters.\nfunc (sh *JLHScoreSignificanceHeuristic) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\treturn source, nil\n}\n\n// -- Mutual Information --\n\n// MutualInformationSignificanceHeuristic implements Mutual information\n// as described in \"Information Retrieval\", Manning et al., Chapter 13.5.1.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_mutual_information\n// for details.\ntype MutualInformationSignificanceHeuristic struct {\n\tbackgroundIsSuperset *bool\n\tincludeNegatives     *bool\n}\n\n// NewMutualInformationSignificanceHeuristic initializes a new instance of\n// MutualInformationSignificanceHeuristic.\nfunc NewMutualInformationSignificanceHeuristic() *MutualInformationSignificanceHeuristic {\n\treturn &MutualInformationSignificanceHeuristic{}\n}\n\n// Name returns the name of the heuristic in the REST interface.\nfunc (sh *MutualInformationSignificanceHeuristic) Name() string {\n\treturn \"mutual_information\"\n}\n\n// BackgroundIsSuperset indicates whether you defined a custom background\n// filter that represents a difference set of documents that you want to\n// compare to.\nfunc (sh *MutualInformationSignificanceHeuristic) BackgroundIsSuperset(backgroundIsSuperset bool) *MutualInformationSignificanceHeuristic {\n\tsh.backgroundIsSuperset = &backgroundIsSuperset\n\treturn sh\n}\n\n// IncludeNegatives indicates whether to filter out the terms that appear\n// much less in the subset than in the background without the subset.\nfunc (sh *MutualInformationSignificanceHeuristic) IncludeNegatives(includeNegatives bool) *MutualInformationSignificanceHeuristic {\n\tsh.includeNegatives = &includeNegatives\n\treturn sh\n}\n\n// Source returns the parameters that need to be added to the REST parameters.\nfunc (sh *MutualInformationSignificanceHeuristic) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif sh.backgroundIsSuperset != nil {\n\t\tsource[\"background_is_superset\"] = *sh.backgroundIsSuperset\n\t}\n\tif sh.includeNegatives != nil {\n\t\tsource[\"include_negatives\"] = *sh.includeNegatives\n\t}\n\treturn source, nil\n}\n\n// -- Percentage Score --\n\n// PercentageScoreSignificanceHeuristic implements the algorithm described\n// in https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_percentage.\ntype PercentageScoreSignificanceHeuristic struct{}\n\n// NewPercentageScoreSignificanceHeuristic initializes a new instance of\n// PercentageScoreSignificanceHeuristic.\nfunc NewPercentageScoreSignificanceHeuristic() *PercentageScoreSignificanceHeuristic {\n\treturn &PercentageScoreSignificanceHeuristic{}\n}\n\n// Name returns the name of the heuristic in the REST interface.\nfunc (sh *PercentageScoreSignificanceHeuristic) Name() string {\n\treturn \"percentage\"\n}\n\n// Source returns the parameters that need to be added to the REST parameters.\nfunc (sh *PercentageScoreSignificanceHeuristic) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\treturn source, nil\n}\n\n// -- Script --\n\n// ScriptSignificanceHeuristic implements a scripted significance heuristic.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_scripted\n// for details.\ntype ScriptSignificanceHeuristic struct {\n\tscript *Script\n}\n\n// NewScriptSignificanceHeuristic initializes a new instance of\n// ScriptSignificanceHeuristic.\nfunc NewScriptSignificanceHeuristic() *ScriptSignificanceHeuristic {\n\treturn &ScriptSignificanceHeuristic{}\n}\n\n// Name returns the name of the heuristic in the REST interface.\nfunc (sh *ScriptSignificanceHeuristic) Name() string {\n\treturn \"script_heuristic\"\n}\n\n// Script specifies the script to use to get custom scores. The following\n// parameters are available in the script: `_subset_freq`, `_superset_freq`,\n// `_subset_size`, and `_superset_size`.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_scripted\n// for details.\nfunc (sh *ScriptSignificanceHeuristic) Script(script *Script) *ScriptSignificanceHeuristic {\n\tsh.script = script\n\treturn sh\n}\n\n// Source returns the parameters that need to be added to the REST parameters.\nfunc (sh *ScriptSignificanceHeuristic) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif sh.script != nil {\n\t\tsrc, err := sh.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"script\"] = src\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_significant_terms_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSignificantTermsAggregation(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"field\":\"crime_type\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithArgs(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().\n\t\tField(\"crime_type\").\n\t\tExecutionHint(\"map\").\n\t\tShardSize(5).\n\t\tMinDocCount(10).\n\t\tBackgroundFilter(NewTermQuery(\"city\", \"London\"))\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"background_filter\":{\"term\":{\"city\":\"London\"}},\"execution_hint\":\"map\",\"field\":\"crime_type\",\"min_doc_count\":10,\"shard_size\":5}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithIncludeExclude(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\").Include(\".*sport.*\").Exclude(\"water_.*\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"exclude\":\"water_.*\",\"field\":\"crime_type\",\"include\":\".*sport.*\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithIncludeExcludeValues(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\").IncludeValues(\"mazda\", \"honda\").ExcludeValues(\"rover\", \"jensen\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"exclude\":[\"rover\",\"jensen\"],\"field\":\"crime_type\",\"include\":[\"mazda\",\"honda\"]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithPartitions(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"account_id\").Partition(0).NumPartitions(20)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"field\":\"account_id\",\"include\":{\"num_partitions\":20,\"partition\":0}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationSubAggregation(t *testing.T) {\n\tcrimeTypesAgg := NewSignificantTermsAggregation().Field(\"crime_type\")\n\tagg := NewTermsAggregation().Field(\"force\")\n\tagg = agg.SubAggregation(\"significantCrimeTypes\", crimeTypesAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"significantCrimeTypes\":{\"significant_terms\":{\"field\":\"crime_type\"}}},\"terms\":{\"field\":\"force\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithMetaData(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\")\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"significant_terms\":{\"field\":\"crime_type\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithChiSquare(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\")\n\tagg = agg.SignificanceHeuristic(\n\t\tNewChiSquareSignificanceHeuristic().\n\t\t\tBackgroundIsSuperset(true).\n\t\t\tIncludeNegatives(false),\n\t)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"chi_square\":{\"background_is_superset\":true,\"include_negatives\":false},\"field\":\"crime_type\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithGND(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\")\n\tagg = agg.SignificanceHeuristic(\n\t\tNewGNDSignificanceHeuristic(),\n\t)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"field\":\"crime_type\",\"gnd\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithJLH(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\")\n\tagg = agg.SignificanceHeuristic(\n\t\tNewJLHScoreSignificanceHeuristic(),\n\t)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"field\":\"crime_type\",\"jlh\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithMutualInformation(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\")\n\tagg = agg.SignificanceHeuristic(\n\t\tNewMutualInformationSignificanceHeuristic().\n\t\t\tBackgroundIsSuperset(false).\n\t\t\tIncludeNegatives(true),\n\t)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"field\":\"crime_type\",\"mutual_information\":{\"background_is_superset\":false,\"include_negatives\":true}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithPercentageScore(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\")\n\tagg = agg.SignificanceHeuristic(\n\t\tNewPercentageScoreSignificanceHeuristic(),\n\t)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"field\":\"crime_type\",\"percentage\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTermsAggregationWithScript(t *testing.T) {\n\tagg := NewSignificantTermsAggregation().Field(\"crime_type\")\n\tagg = agg.SignificanceHeuristic(\n\t\tNewScriptSignificanceHeuristic().\n\t\t\tScript(NewScript(\"_subset_freq/(_superset_freq - _subset_freq + 1)\")),\n\t)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_terms\":{\"field\":\"crime_type\",\"script_heuristic\":{\"script\":{\"source\":\"_subset_freq/(_superset_freq - _subset_freq + 1)\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_significant_text.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SignificantTextAggregation returns interesting or unusual occurrences\n// of free-text terms in a set.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significanttext-aggregation.html\ntype SignificantTextAggregation struct {\n\tfield           string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\n\tsourceFieldNames      []string\n\tfilterDuplicateText   *bool\n\tincludeExclude        *TermsAggregationIncludeExclude\n\tfilter                Query\n\tbucketCountThresholds *BucketCountThresholds\n\tsignificanceHeuristic SignificanceHeuristic\n}\n\nfunc NewSignificantTextAggregation() *SignificantTextAggregation {\n\treturn &SignificantTextAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *SignificantTextAggregation) Field(field string) *SignificantTextAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) SubAggregation(name string, subAggregation Aggregation) *SignificantTextAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *SignificantTextAggregation) Meta(metaData map[string]interface{}) *SignificantTextAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) SourceFieldNames(names ...string) *SignificantTextAggregation {\n\ta.sourceFieldNames = names\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) FilterDuplicateText(filter bool) *SignificantTextAggregation {\n\ta.filterDuplicateText = &filter\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) MinDocCount(minDocCount int64) *SignificantTextAggregation {\n\tif a.bucketCountThresholds == nil {\n\t\ta.bucketCountThresholds = &BucketCountThresholds{}\n\t}\n\ta.bucketCountThresholds.MinDocCount = &minDocCount\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) ShardMinDocCount(shardMinDocCount int64) *SignificantTextAggregation {\n\tif a.bucketCountThresholds == nil {\n\t\ta.bucketCountThresholds = &BucketCountThresholds{}\n\t}\n\ta.bucketCountThresholds.ShardMinDocCount = &shardMinDocCount\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) Size(size int) *SignificantTextAggregation {\n\tif a.bucketCountThresholds == nil {\n\t\ta.bucketCountThresholds = &BucketCountThresholds{}\n\t}\n\ta.bucketCountThresholds.RequiredSize = &size\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) ShardSize(shardSize int) *SignificantTextAggregation {\n\tif a.bucketCountThresholds == nil {\n\t\ta.bucketCountThresholds = &BucketCountThresholds{}\n\t}\n\ta.bucketCountThresholds.ShardSize = &shardSize\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) BackgroundFilter(filter Query) *SignificantTextAggregation {\n\ta.filter = filter\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) SignificanceHeuristic(heuristic SignificanceHeuristic) *SignificantTextAggregation {\n\ta.significanceHeuristic = heuristic\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) Include(regexp string) *SignificantTextAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Include = regexp\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) IncludeValues(values ...interface{}) *SignificantTextAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.IncludeValues = append(a.includeExclude.IncludeValues, values...)\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) Exclude(regexp string) *SignificantTextAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Exclude = regexp\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) ExcludeValues(values ...interface{}) *SignificantTextAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.ExcludeValues = append(a.includeExclude.ExcludeValues, values...)\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) Partition(p int) *SignificantTextAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Partition = p\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) NumPartitions(n int) *SignificantTextAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.NumPartitions = n\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) IncludeExclude(includeExclude *TermsAggregationIncludeExclude) *SignificantTextAggregation {\n\ta.includeExclude = includeExclude\n\treturn a\n}\n\nfunc (a *SignificantTextAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"query\" : {\n\t//         \"match\" : {\"content\" : \"Bird flu\"}\n\t//     },\n\t//     \"aggregations\" : {\n\t//         \"my_sample\" : {\n\t//             \"sampler\": {\n\t//                 \"shard_size\" : 100\n\t//             },\n\t//             \"aggregations\": {\n\t//                 \"keywords\" : {\n\t//                     \"significant_text\" : { \"field\" : \"content\" }\n\t//                 }\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the\n\t//   { \"significant_text\" : { \"field\" : \"content\" }\n\t// part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"significant_text\"] = opts\n\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.bucketCountThresholds != nil {\n\t\tif a.bucketCountThresholds.RequiredSize != nil {\n\t\t\topts[\"size\"] = (*a.bucketCountThresholds).RequiredSize\n\t\t}\n\t\tif a.bucketCountThresholds.ShardSize != nil {\n\t\t\topts[\"shard_size\"] = (*a.bucketCountThresholds).ShardSize\n\t\t}\n\t\tif a.bucketCountThresholds.MinDocCount != nil {\n\t\t\topts[\"min_doc_count\"] = (*a.bucketCountThresholds).MinDocCount\n\t\t}\n\t\tif a.bucketCountThresholds.ShardMinDocCount != nil {\n\t\t\topts[\"shard_min_doc_count\"] = (*a.bucketCountThresholds).ShardMinDocCount\n\t\t}\n\t}\n\tif a.filter != nil {\n\t\tsrc, err := a.filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"background_filter\"] = src\n\t}\n\tif a.significanceHeuristic != nil {\n\t\tname := a.significanceHeuristic.Name()\n\t\tsrc, err := a.significanceHeuristic.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[name] = src\n\t}\n\t// Include/Exclude\n\tif ie := a.includeExclude; ie != nil {\n\t\t// Include\n\t\tif ie.Include != \"\" {\n\t\t\topts[\"include\"] = ie.Include\n\t\t} else if len(ie.IncludeValues) > 0 {\n\t\t\topts[\"include\"] = ie.IncludeValues\n\t\t} else if ie.NumPartitions > 0 {\n\t\t\tinc := make(map[string]interface{})\n\t\t\tinc[\"partition\"] = ie.Partition\n\t\t\tinc[\"num_partitions\"] = ie.NumPartitions\n\t\t\topts[\"include\"] = inc\n\t\t}\n\t\t// Exclude\n\t\tif ie.Exclude != \"\" {\n\t\t\topts[\"exclude\"] = ie.Exclude\n\t\t} else if len(ie.ExcludeValues) > 0 {\n\t\t\topts[\"exclude\"] = ie.ExcludeValues\n\t\t}\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_significant_text_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSignificantTextAggregation(t *testing.T) {\n\tagg := NewSignificantTextAggregation().Field(\"content\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_text\":{\"field\":\"content\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTextAggregationWithArgs(t *testing.T) {\n\tagg := NewSignificantTextAggregation().\n\t\tField(\"content\").\n\t\tShardSize(5).\n\t\tMinDocCount(10).\n\t\tBackgroundFilter(NewTermQuery(\"city\", \"London\"))\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_text\":{\"background_filter\":{\"term\":{\"city\":\"London\"}},\"field\":\"content\",\"min_doc_count\":10,\"shard_size\":5}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTextAggregationWithPartitions(t *testing.T) {\n\tagg := NewSignificantTextAggregation().Field(\"account_id\").Partition(0).NumPartitions(20)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"significant_text\":{\"field\":\"account_id\",\"include\":{\"num_partitions\":20,\"partition\":0}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSignificantTextAggregationWithMetaData(t *testing.T) {\n\tagg := NewSignificantTextAggregation().Field(\"content\")\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"significant_text\":{\"field\":\"content\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_bucket_terms.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"fmt\"\n\n// TermsAggregation is a multi-bucket value source based aggregation\n// where buckets are dynamically built - one per unique value.\n//\n// See: http://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-terms-aggregation.html\ntype TermsAggregation struct {\n\tfield           string\n\tscript          *Script\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\n\tsize                  *int\n\tshardSize             *int\n\trequiredSize          *int\n\tminDocCount           *int\n\tshardMinDocCount      *int\n\tvalueType             string\n\tincludeExclude        *TermsAggregationIncludeExclude\n\texecutionHint         string\n\tcollectionMode        string\n\tshowTermDocCountError *bool\n\torder                 []TermsOrder\n}\n\nfunc NewTermsAggregation() *TermsAggregation {\n\treturn &TermsAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *TermsAggregation) Field(field string) *TermsAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *TermsAggregation) Script(script *Script) *TermsAggregation {\n\ta.script = script\n\treturn a\n}\n\n// Missing configures the value to use when documents miss a value.\nfunc (a *TermsAggregation) Missing(missing interface{}) *TermsAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *TermsAggregation) SubAggregation(name string, subAggregation Aggregation) *TermsAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *TermsAggregation) Meta(metaData map[string]interface{}) *TermsAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *TermsAggregation) Size(size int) *TermsAggregation {\n\ta.size = &size\n\treturn a\n}\n\nfunc (a *TermsAggregation) RequiredSize(requiredSize int) *TermsAggregation {\n\ta.requiredSize = &requiredSize\n\treturn a\n}\n\nfunc (a *TermsAggregation) ShardSize(shardSize int) *TermsAggregation {\n\ta.shardSize = &shardSize\n\treturn a\n}\n\nfunc (a *TermsAggregation) MinDocCount(minDocCount int) *TermsAggregation {\n\ta.minDocCount = &minDocCount\n\treturn a\n}\n\nfunc (a *TermsAggregation) ShardMinDocCount(shardMinDocCount int) *TermsAggregation {\n\ta.shardMinDocCount = &shardMinDocCount\n\treturn a\n}\n\nfunc (a *TermsAggregation) Include(regexp string) *TermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Include = regexp\n\treturn a\n}\n\nfunc (a *TermsAggregation) IncludeValues(values ...interface{}) *TermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.IncludeValues = append(a.includeExclude.IncludeValues, values...)\n\treturn a\n}\n\nfunc (a *TermsAggregation) Exclude(regexp string) *TermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Exclude = regexp\n\treturn a\n}\n\nfunc (a *TermsAggregation) ExcludeValues(values ...interface{}) *TermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.ExcludeValues = append(a.includeExclude.ExcludeValues, values...)\n\treturn a\n}\n\nfunc (a *TermsAggregation) Partition(p int) *TermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.Partition = p\n\treturn a\n}\n\nfunc (a *TermsAggregation) NumPartitions(n int) *TermsAggregation {\n\tif a.includeExclude == nil {\n\t\ta.includeExclude = &TermsAggregationIncludeExclude{}\n\t}\n\ta.includeExclude.NumPartitions = n\n\treturn a\n}\n\nfunc (a *TermsAggregation) IncludeExclude(includeExclude *TermsAggregationIncludeExclude) *TermsAggregation {\n\ta.includeExclude = includeExclude\n\treturn a\n}\n\n// ValueType can be string, long, or double.\nfunc (a *TermsAggregation) ValueType(valueType string) *TermsAggregation {\n\ta.valueType = valueType\n\treturn a\n}\n\nfunc (a *TermsAggregation) Order(order string, asc bool) *TermsAggregation {\n\ta.order = append(a.order, TermsOrder{Field: order, Ascending: asc})\n\treturn a\n}\n\nfunc (a *TermsAggregation) OrderByCount(asc bool) *TermsAggregation {\n\t// \"order\" : { \"_count\" : \"asc\" }\n\ta.order = append(a.order, TermsOrder{Field: \"_count\", Ascending: asc})\n\treturn a\n}\n\nfunc (a *TermsAggregation) OrderByCountAsc() *TermsAggregation {\n\treturn a.OrderByCount(true)\n}\n\nfunc (a *TermsAggregation) OrderByCountDesc() *TermsAggregation {\n\treturn a.OrderByCount(false)\n}\n\n// Deprecated: Use OrderByKey instead.\nfunc (a *TermsAggregation) OrderByTerm(asc bool) *TermsAggregation {\n\t// \"order\" : { \"_term\" : \"asc\" }\n\ta.order = append(a.order, TermsOrder{Field: \"_term\", Ascending: asc})\n\treturn a\n}\n\n// Deprecated: Use OrderByKeyAsc instead.\nfunc (a *TermsAggregation) OrderByTermAsc() *TermsAggregation {\n\treturn a.OrderByTerm(true)\n}\n\n// Deprecated: Use OrderByKeyDesc instead.\nfunc (a *TermsAggregation) OrderByTermDesc() *TermsAggregation {\n\treturn a.OrderByTerm(false)\n}\n\nfunc (a *TermsAggregation) OrderByKey(asc bool) *TermsAggregation {\n\t// \"order\" : { \"_term\" : \"asc\" }\n\ta.order = append(a.order, TermsOrder{Field: \"_key\", Ascending: asc})\n\treturn a\n}\n\nfunc (a *TermsAggregation) OrderByKeyAsc() *TermsAggregation {\n\treturn a.OrderByKey(true)\n}\n\nfunc (a *TermsAggregation) OrderByKeyDesc() *TermsAggregation {\n\treturn a.OrderByKey(false)\n}\n\n// OrderByAggregation creates a bucket ordering strategy which sorts buckets\n// based on a single-valued calc get.\nfunc (a *TermsAggregation) OrderByAggregation(aggName string, asc bool) *TermsAggregation {\n\t// {\n\t//     \"aggs\" : {\n\t//         \"genders\" : {\n\t//             \"terms\" : {\n\t//                 \"field\" : \"gender\",\n\t//                 \"order\" : { \"avg_height\" : \"desc\" }\n\t//             },\n\t//             \"aggs\" : {\n\t//                 \"avg_height\" : { \"avg\" : { \"field\" : \"height\" } }\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\ta.order = append(a.order, TermsOrder{Field: aggName, Ascending: asc})\n\treturn a\n}\n\n// OrderByAggregationAndMetric creates a bucket ordering strategy which\n// sorts buckets based on a multi-valued calc get.\nfunc (a *TermsAggregation) OrderByAggregationAndMetric(aggName, metric string, asc bool) *TermsAggregation {\n\t// {\n\t//     \"aggs\" : {\n\t//         \"genders\" : {\n\t//             \"terms\" : {\n\t//                 \"field\" : \"gender\",\n\t//                 \"order\" : { \"height_stats.avg\" : \"desc\" }\n\t//             },\n\t//             \"aggs\" : {\n\t//                 \"height_stats\" : { \"stats\" : { \"field\" : \"height\" } }\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\ta.order = append(a.order, TermsOrder{Field: aggName + \".\" + metric, Ascending: asc})\n\treturn a\n}\n\nfunc (a *TermsAggregation) ExecutionHint(hint string) *TermsAggregation {\n\ta.executionHint = hint\n\treturn a\n}\n\n// Collection mode can be depth_first or breadth_first as of 1.4.0.\nfunc (a *TermsAggregation) CollectionMode(collectionMode string) *TermsAggregation {\n\ta.collectionMode = collectionMode\n\treturn a\n}\n\nfunc (a *TermsAggregation) ShowTermDocCountError(showTermDocCountError bool) *TermsAggregation {\n\ta.showTermDocCountError = &showTermDocCountError\n\treturn a\n}\n\nfunc (a *TermsAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"genders\" : {\n\t//        \"terms\" : { \"field\" : \"gender\" }\n\t//      }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"terms\" : { \"field\" : \"gender\" } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"terms\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\t// TermsBuilder\n\tif a.size != nil && *a.size >= 0 {\n\t\topts[\"size\"] = *a.size\n\t}\n\tif a.shardSize != nil && *a.shardSize >= 0 {\n\t\topts[\"shard_size\"] = *a.shardSize\n\t}\n\tif a.requiredSize != nil && *a.requiredSize >= 0 {\n\t\topts[\"required_size\"] = *a.requiredSize\n\t}\n\tif a.minDocCount != nil && *a.minDocCount >= 0 {\n\t\topts[\"min_doc_count\"] = *a.minDocCount\n\t}\n\tif a.shardMinDocCount != nil && *a.shardMinDocCount >= 0 {\n\t\topts[\"shard_min_doc_count\"] = *a.shardMinDocCount\n\t}\n\tif a.showTermDocCountError != nil {\n\t\topts[\"show_term_doc_count_error\"] = *a.showTermDocCountError\n\t}\n\tif a.collectionMode != \"\" {\n\t\topts[\"collect_mode\"] = a.collectionMode\n\t}\n\tif a.valueType != \"\" {\n\t\topts[\"value_type\"] = a.valueType\n\t}\n\tif len(a.order) > 0 {\n\t\tvar orderSlice []interface{}\n\t\tfor _, order := range a.order {\n\t\t\tsrc, err := order.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\torderSlice = append(orderSlice, src)\n\t\t}\n\t\topts[\"order\"] = orderSlice\n\t}\n\n\t// Include/Exclude\n\tif ie := a.includeExclude; ie != nil {\n\t\tif err := ie.MergeInto(opts); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif a.executionHint != \"\" {\n\t\topts[\"execution_hint\"] = a.executionHint\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n\n// TermsAggregationIncludeExclude allows for include/exclude in a TermsAggregation.\ntype TermsAggregationIncludeExclude struct {\n\tInclude       string\n\tExclude       string\n\tIncludeValues []interface{}\n\tExcludeValues []interface{}\n\tPartition     int\n\tNumPartitions int\n}\n\n// Source returns a JSON serializable struct.\nfunc (ie *TermsAggregationIncludeExclude) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\t// Include\n\tif ie.Include != \"\" {\n\t\tsource[\"include\"] = ie.Include\n\t} else if len(ie.IncludeValues) > 0 {\n\t\tsource[\"include\"] = ie.IncludeValues\n\t} else if ie.NumPartitions > 0 {\n\t\tinc := make(map[string]interface{})\n\t\tinc[\"partition\"] = ie.Partition\n\t\tinc[\"num_partitions\"] = ie.NumPartitions\n\t\tsource[\"include\"] = inc\n\t}\n\n\t// Exclude\n\tif ie.Exclude != \"\" {\n\t\tsource[\"exclude\"] = ie.Exclude\n\t} else if len(ie.ExcludeValues) > 0 {\n\t\tsource[\"exclude\"] = ie.ExcludeValues\n\t}\n\n\treturn source, nil\n}\n\n// MergeInto merges the values of the include/exclude options into source.\nfunc (ie *TermsAggregationIncludeExclude) MergeInto(source map[string]interface{}) error {\n\tvalues, err := ie.Source()\n\tif err != nil {\n\t\treturn err\n\t}\n\tmv, ok := values.(map[string]interface{})\n\tif !ok {\n\t\treturn fmt.Errorf(\"IncludeExclude: expected a map[string]interface{}, got %T\", values)\n\t}\n\tfor k, v := range mv {\n\t\tsource[k] = v\n\t}\n\treturn nil\n}\n\n// TermsOrder specifies a single order field for a terms aggregation.\ntype TermsOrder struct {\n\tField     string\n\tAscending bool\n}\n\n// Source returns serializable JSON of the TermsOrder.\nfunc (order *TermsOrder) Source() (interface{}, error) {\n\tsource := make(map[string]string)\n\tif order.Ascending {\n\t\tsource[order.Field] = \"asc\"\n\t} else {\n\t\tsource[order.Field] = \"desc\"\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_bucket_terms_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestAggsBucketTermsIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\tresp, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tAggregation(\"retweets\", NewTermsAggregation().Field(\"retweets\")).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif resp.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil\")\n\t}\n\tif want, have := int64(3), resp.TotalHits(); want != have {\n\t\tt.Errorf(\"TotalHits(): want %d, have %d\", want, have)\n\t}\n\n\taggs := resp.Aggregations\n\tif aggs == nil {\n\t\tt.Fatalf(\"expected Aggregations != nil\")\n\t}\n\n\tagg, found := aggs.Terms(\"retweets\")\n\tif !found {\n\t\tt.Fatal(\"expected to find aggregation by name\")\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected != nil\")\n\t}\n\tif want, have := 3, len(agg.Buckets); want != have {\n\t\tt.Fatalf(\"len(Buckets): want %d, have %d\", want, have)\n\t}\n\n\t// Element #0\n\tif want, have := float64(0), agg.Buckets[0].Key; want != have {\n\t\tt.Errorf(\"Buckets[0].Key: want %v, have %v\", want, have)\n\t}\n\tif want, have := json.Number(\"0\"), agg.Buckets[0].KeyNumber; want != have {\n\t\tt.Errorf(\"agg.Buckets[0].KeyNumber: want %q, have %q\", want, have)\n\t}\n\tif have, err := agg.Buckets[0].KeyNumber.Int64(); err != nil {\n\t\tt.Errorf(\"Buckets[0].KeyNumber.Int64(): %v\", err)\n\t} else if want := int64(0); want != have {\n\t\tt.Errorf(\"Buckets[0].KeyNumber.Int64(): want %d, have %d\", want, have)\n\t}\n\tif want, have := \"0\", agg.Buckets[0].KeyNumber.String(); want != have {\n\t\tt.Errorf(\"Buckets[0].KeyNumber.String(): want %q, have %q\", want, have)\n\t}\n\tif want, have := int64(1), agg.Buckets[0].DocCount; want != have {\n\t\tt.Errorf(\"Buckets[0].DocCount: want %d, have %d\", want, have)\n\t}\n\n\t// Element #1\n\tif want, have := float64(12), agg.Buckets[1].Key; want != have {\n\t\tt.Errorf(\"Buckets[1].Key: want %v, have %v\", want, have)\n\t}\n\tif have, err := agg.Buckets[1].KeyNumber.Int64(); err != nil {\n\t\tt.Errorf(\"Buckets[1].KeyNumber.Int64(): %v\", err)\n\t} else if want := int64(12); want != have {\n\t\tt.Errorf(\"Buckets[1].KeyNumber.Int64(): want %d, have %d\", want, have)\n\t}\n\tif want, have := \"12\", agg.Buckets[1].KeyNumber.String(); want != have {\n\t\tt.Errorf(\"Buckets[1].KeyNumber.String(): want %q, have %q\", want, have)\n\t}\n\tif want, have := int64(1), agg.Buckets[1].DocCount; want != have {\n\t\tt.Errorf(\"Buckets[1].DocCount: want %d, have %d\", want, have)\n\t}\n\n\t// Element #2\n\tif want, have := float64(108), agg.Buckets[2].Key; want != have {\n\t\tt.Errorf(\"Buckets[2].Key: want %v, have %v\", want, have)\n\t}\n\tif want, have := json.Number(\"108\"), agg.Buckets[2].KeyNumber; want != have {\n\t\tt.Errorf(\"Buckets[2].KeyNumber: want %q, have %q\", want, have)\n\t}\n\tif have, err := agg.Buckets[2].KeyNumber.Int64(); err != nil {\n\t\tt.Errorf(\"Buckets[2].KeyNumber.Int64(): %v\", err)\n\t} else if want := int64(108); want != have {\n\t\tt.Errorf(\"Buckets[2].KeyNumber.Int64(): want %d, have %d\", want, have)\n\t}\n\tif want, have := \"108\", agg.Buckets[2].KeyNumber.String(); want != have {\n\t\tt.Errorf(\"Buckets[2].KeyNumber.String(): want %q, have %q\", want, have)\n\t}\n\tif want, have := int64(1), agg.Buckets[2].DocCount; want != have {\n\t\tt.Errorf(\"Buckets[2].DocCount: want %d, have %d\", want, have)\n\t}\n\n}\n"
  },
  {
    "path": "search_aggs_bucket_terms_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestTermsAggregation(t *testing.T) {\n\tagg := NewTermsAggregation().Field(\"gender\").Size(10).OrderByKeyDesc()\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"field\":\"gender\",\"order\":[{\"_key\":\"desc\"}],\"size\":10}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsAggregationWithSubAggregation(t *testing.T) {\n\tsubAgg := NewAvgAggregation().Field(\"height\")\n\tagg := NewTermsAggregation().Field(\"gender\").Size(10).\n\t\tOrderByAggregation(\"avg_height\", false)\n\tagg = agg.SubAggregation(\"avg_height\", subAgg)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"avg_height\":{\"avg\":{\"field\":\"height\"}}},\"terms\":{\"field\":\"gender\",\"order\":[{\"avg_height\":\"desc\"}],\"size\":10}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsAggregationWithMultipleSubAggregation(t *testing.T) {\n\tsubAgg1 := NewAvgAggregation().Field(\"height\")\n\tsubAgg2 := NewAvgAggregation().Field(\"width\")\n\tagg := NewTermsAggregation().Field(\"gender\").Size(10).\n\t\tOrderByAggregation(\"avg_height\", false)\n\tagg = agg.SubAggregation(\"avg_height\", subAgg1)\n\tagg = agg.SubAggregation(\"avg_width\", subAgg2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"aggregations\":{\"avg_height\":{\"avg\":{\"field\":\"height\"}},\"avg_width\":{\"avg\":{\"field\":\"width\"}}},\"terms\":{\"field\":\"gender\",\"order\":[{\"avg_height\":\"desc\"}],\"size\":10}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsAggregationWithMetaData(t *testing.T) {\n\tagg := NewTermsAggregation().Field(\"gender\").Size(10).OrderByKeyDesc()\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"terms\":{\"field\":\"gender\",\"order\":[{\"_key\":\"desc\"}],\"size\":10}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsAggregationWithMissing(t *testing.T) {\n\tagg := NewTermsAggregation().Field(\"gender\").Size(10).Missing(\"n/a\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"field\":\"gender\",\"missing\":\"n/a\",\"size\":10}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsAggregationWithIncludeExclude(t *testing.T) {\n\tagg := NewTermsAggregation().Field(\"tags\").Include(\".*sport.*\").Exclude(\"water_.*\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"exclude\":\"water_.*\",\"field\":\"tags\",\"include\":\".*sport.*\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsAggregationWithIncludeExcludeValues(t *testing.T) {\n\tagg := NewTermsAggregation().Field(\"make\").IncludeValues(\"mazda\", \"honda\").ExcludeValues(\"rover\", \"jensen\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"exclude\":[\"rover\",\"jensen\"],\"field\":\"make\",\"include\":[\"mazda\",\"honda\"]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsAggregationWithPartitions(t *testing.T) {\n\tagg := NewTermsAggregation().Field(\"account_id\").Partition(0).NumPartitions(20)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"field\":\"account_id\",\"include\":{\"num_partitions\":20,\"partition\":0}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_matrix_stats.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MatrixMatrixStatsAggregation is a multi-value metrics aggregation\n// that computes stats over numeric values extracted from the\n// aggregated documents. These values can be extracted either from\n// specific numeric fields in the documents, or be generated by a provided script.\n//\n// The stats that are returned consist of: min, max, sum, count and avg.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-stats-aggregation.html\n// for details.\ntype MatrixStatsAggregation struct {\n\tfields          []string\n\tmissing         interface{}\n\tformat          string\n\tvalueType       interface{}\n\tmode            string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\n// NewMatrixStatsAggregation initializes a new MatrixStatsAggregation.\nfunc NewMatrixStatsAggregation() *MatrixStatsAggregation {\n\treturn &MatrixStatsAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *MatrixStatsAggregation) Fields(fields ...string) *MatrixStatsAggregation {\n\ta.fields = append(a.fields, fields...)\n\treturn a\n}\n\n// Missing configures the value to use when documents miss a value.\nfunc (a *MatrixStatsAggregation) Missing(missing interface{}) *MatrixStatsAggregation {\n\ta.missing = missing\n\treturn a\n}\n\n// Mode specifies how to operate. Valid values are: sum, avg, median, min, or max.\nfunc (a *MatrixStatsAggregation) Mode(mode string) *MatrixStatsAggregation {\n\ta.mode = mode\n\treturn a\n}\n\nfunc (a *MatrixStatsAggregation) Format(format string) *MatrixStatsAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *MatrixStatsAggregation) ValueType(valueType interface{}) *MatrixStatsAggregation {\n\ta.valueType = valueType\n\treturn a\n}\n\nfunc (a *MatrixStatsAggregation) SubAggregation(name string, subAggregation Aggregation) *MatrixStatsAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MatrixStatsAggregation) Meta(metaData map[string]interface{}) *MatrixStatsAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// Source returns the JSON to serialize into the request, or an error.\nfunc (a *MatrixStatsAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"matrixstats\" : {\n\t//        \"matrix_stats\" : {\n\t//          \"fields\" : [\"poverty\", \"income\"],\n\t//          \"missing\": {\"income\": 50000},\n\t//          \"mode\": \"avg\",\n\t//          ...\n\t//        }\n\t//      }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"matrix_stats\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"matrix_stats\"] = opts\n\n\t// MatrixStatsAggregationBuilder\n\topts[\"fields\"] = a.fields\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.valueType != nil {\n\t\topts[\"value_type\"] = a.valueType\n\t}\n\tif a.mode != \"\" {\n\t\topts[\"mode\"] = a.mode\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_matrix_stats_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMatrixStatsAggregation(t *testing.T) {\n\tagg := NewMatrixStatsAggregation().\n\t\tFields(\"poverty\", \"income\").\n\t\tMissing(map[string]interface{}{\n\t\t\t\"income\": 50000,\n\t\t}).\n\t\tMode(\"avg\").\n\t\tFormat(\"0000.0\").\n\t\tValueType(\"double\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"matrix_stats\":{\"fields\":[\"poverty\",\"income\"],\"format\":\"0000.0\",\"missing\":{\"income\":50000},\"mode\":\"avg\",\"value_type\":\"double\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMatrixStatsAggregationWithMetaData(t *testing.T) {\n\tagg := NewMatrixStatsAggregation().\n\t\tFields(\"poverty\", \"income\").\n\t\tMeta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"matrix_stats\":{\"fields\":[\"poverty\",\"income\"]},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_avg.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// AvgAggregation is a single-value metrics aggregation that computes\n// the average of numeric values that are extracted from the\n// aggregated documents. These values can be extracted either from\n// specific numeric fields in the documents, or be generated by\n// a provided script.\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-avg-aggregation.html\ntype AvgAggregation struct {\n\tfield           string\n\tscript          *Script\n\tformat          string\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewAvgAggregation() *AvgAggregation {\n\treturn &AvgAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *AvgAggregation) Field(field string) *AvgAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *AvgAggregation) Script(script *Script) *AvgAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *AvgAggregation) Format(format string) *AvgAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *AvgAggregation) Missing(missing interface{}) *AvgAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *AvgAggregation) SubAggregation(name string, subAggregation Aggregation) *AvgAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *AvgAggregation) Meta(metaData map[string]interface{}) *AvgAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *AvgAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"avg_grade\" : { \"avg\" : { \"field\" : \"grade\" } }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"avg\" : { \"field\" : \"grade\" } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"avg\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_avg_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestAvgAggregation(t *testing.T) {\n\tagg := NewAvgAggregation().Field(\"grade\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"avg\":{\"field\":\"grade\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestAvgAggregationWithOptions(t *testing.T) {\n\tagg := NewAvgAggregation().Field(\"grade\").Format(\"000.0\").Missing(1.2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"avg\":{\"field\":\"grade\",\"format\":\"000.0\",\"missing\":1.2}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestAvgAggregationWithMetaData(t *testing.T) {\n\tagg := NewAvgAggregation().Field(\"grade\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"avg\":{\"field\":\"grade\"},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_cardinality.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// CardinalityAggregation is a single-value metrics aggregation that\n// calculates an approximate count of distinct values.\n// Values can be extracted either from specific fields in the document\n// or generated by a script.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-cardinality-aggregation.html\ntype CardinalityAggregation struct {\n\tfield              string\n\tscript             *Script\n\tformat             string\n\tmissing            interface{}\n\tsubAggregations    map[string]Aggregation\n\tmeta               map[string]interface{}\n\tprecisionThreshold *int64\n\trehash             *bool\n}\n\nfunc NewCardinalityAggregation() *CardinalityAggregation {\n\treturn &CardinalityAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *CardinalityAggregation) Field(field string) *CardinalityAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *CardinalityAggregation) Script(script *Script) *CardinalityAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *CardinalityAggregation) Format(format string) *CardinalityAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *CardinalityAggregation) Missing(missing interface{}) *CardinalityAggregation {\n\ta.missing = missing\n\treturn a\n}\nfunc (a *CardinalityAggregation) SubAggregation(name string, subAggregation Aggregation) *CardinalityAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *CardinalityAggregation) Meta(metaData map[string]interface{}) *CardinalityAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *CardinalityAggregation) PrecisionThreshold(threshold int64) *CardinalityAggregation {\n\ta.precisionThreshold = &threshold\n\treturn a\n}\n\nfunc (a *CardinalityAggregation) Rehash(rehash bool) *CardinalityAggregation {\n\ta.rehash = &rehash\n\treturn a\n}\n\nfunc (a *CardinalityAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"author_count\" : {\n\t//        \"cardinality\" : { \"field\" : \"author\" }\n\t//      }\n\t//    }\n\t//\t}\n\t// This method returns only the \"cardinality\" : { \"field\" : \"author\" } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"cardinality\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.precisionThreshold != nil {\n\t\topts[\"precision_threshold\"] = *a.precisionThreshold\n\t}\n\tif a.rehash != nil {\n\t\topts[\"rehash\"] = *a.rehash\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_cardinality_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestCardinalityAggregation(t *testing.T) {\n\tagg := NewCardinalityAggregation().Field(\"author.hash\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"cardinality\":{\"field\":\"author.hash\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCardinalityAggregationWithOptions(t *testing.T) {\n\tagg := NewCardinalityAggregation().\n\t\tField(\"author.hash\").\n\t\tPrecisionThreshold(100).\n\t\tRehash(true).\n\t\tMissing(1.2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"cardinality\":{\"field\":\"author.hash\",\"missing\":1.2,\"precision_threshold\":100,\"rehash\":true}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCardinalityAggregationWithFormat(t *testing.T) {\n\tagg := NewCardinalityAggregation().Field(\"author.hash\").Format(\"00000\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"cardinality\":{\"field\":\"author.hash\",\"format\":\"00000\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCardinalityAggregationWithMetaData(t *testing.T) {\n\tagg := NewCardinalityAggregation().Field(\"author.hash\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"cardinality\":{\"field\":\"author.hash\"},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_extended_stats.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// ExtendedExtendedStatsAggregation is a multi-value metrics aggregation that\n// computes stats over numeric values extracted from the aggregated documents.\n// These values can be extracted either from specific numeric fields\n// in the documents, or be generated by a provided script.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-extendedstats-aggregation.html\ntype ExtendedStatsAggregation struct {\n\tfield           string\n\tscript          *Script\n\tformat          string\n\tmissing         interface{}\n\tsigma           *float64\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewExtendedStatsAggregation() *ExtendedStatsAggregation {\n\treturn &ExtendedStatsAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *ExtendedStatsAggregation) Field(field string) *ExtendedStatsAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *ExtendedStatsAggregation) Script(script *Script) *ExtendedStatsAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *ExtendedStatsAggregation) Format(format string) *ExtendedStatsAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *ExtendedStatsAggregation) Missing(missing interface{}) *ExtendedStatsAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *ExtendedStatsAggregation) Sigma(sigma float64) *ExtendedStatsAggregation {\n\ta.sigma = &sigma\n\treturn a\n}\n\nfunc (a *ExtendedStatsAggregation) SubAggregation(name string, subAggregation Aggregation) *ExtendedStatsAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *ExtendedStatsAggregation) Meta(metaData map[string]interface{}) *ExtendedStatsAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *ExtendedStatsAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"grades_stats\" : { \"extended_stats\" : { \"field\" : \"grade\" } }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"extended_stats\" : { \"field\" : \"grade\" } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"extended_stats\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif v := a.missing; v != nil {\n\t\topts[\"missing\"] = v\n\t}\n\tif v := a.sigma; v != nil {\n\t\topts[\"sigma\"] = *v\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_extended_stats_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestExtendedStatsAggregation(t *testing.T) {\n\tagg := NewExtendedStatsAggregation().Field(\"grade\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"extended_stats\":{\"field\":\"grade\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestExtendedStatsAggregationWithOptions(t *testing.T) {\n\tagg := NewExtendedStatsAggregation().\n\t\tField(\"grade\").\n\t\tFormat(\"000.0\").\n\t\tMissing(1.2).\n\t\tSigma(3.1415)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"extended_stats\":{\"field\":\"grade\",\"format\":\"000.0\",\"missing\":1.2,\"sigma\":3.1415}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_geo_bounds.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// GeoBoundsAggregation is a metric aggregation that computes the\n// bounding box containing all geo_point values for a field.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-geobounds-aggregation.html\ntype GeoBoundsAggregation struct {\n\tfield           string\n\tscript          *Script\n\twrapLongitude   *bool\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewGeoBoundsAggregation() *GeoBoundsAggregation {\n\treturn &GeoBoundsAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *GeoBoundsAggregation) Field(field string) *GeoBoundsAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *GeoBoundsAggregation) Script(script *Script) *GeoBoundsAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *GeoBoundsAggregation) WrapLongitude(wrapLongitude bool) *GeoBoundsAggregation {\n\ta.wrapLongitude = &wrapLongitude\n\treturn a\n}\n\nfunc (a *GeoBoundsAggregation) SubAggregation(name string, subAggregation Aggregation) *GeoBoundsAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *GeoBoundsAggregation) Meta(metaData map[string]interface{}) *GeoBoundsAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *GeoBoundsAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"query\" : {\n\t//         \"match\" : { \"business_type\" : \"shop\" }\n\t//     },\n\t//     \"aggs\" : {\n\t//         \"viewport\" : {\n\t//             \"geo_bounds\" : {\n\t//                 \"field\" : \"location\"\n\t//                 \"wrap_longitude\" : \"true\"\n\t//             }\n\t//         }\n\t//     }\n\t// }\n\t//\n\t// This method returns only the { \"geo_bounds\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"geo_bounds\"] = opts\n\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.wrapLongitude != nil {\n\t\topts[\"wrap_longitude\"] = *a.wrapLongitude\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_geo_bounds_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGeoBoundsAggregation(t *testing.T) {\n\tagg := NewGeoBoundsAggregation().Field(\"location\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_bounds\":{\"field\":\"location\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoBoundsAggregationWithWrapLongitude(t *testing.T) {\n\tagg := NewGeoBoundsAggregation().Field(\"location\").WrapLongitude(true)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_bounds\":{\"field\":\"location\",\"wrap_longitude\":true}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoBoundsAggregationWithMetaData(t *testing.T) {\n\tagg := NewGeoBoundsAggregation().Field(\"location\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_bounds\":{\"field\":\"location\"},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_geo_centroid.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// GeoCentroidAggregation is a metric aggregation that computes the weighted centroid\n// from all coordinate values for a Geo-point datatype field.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-geocentroid-aggregation.html\ntype GeoCentroidAggregation struct {\n\tfield           string\n\tscript          *Script\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewGeoCentroidAggregation() *GeoCentroidAggregation {\n\treturn &GeoCentroidAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *GeoCentroidAggregation) Field(field string) *GeoCentroidAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *GeoCentroidAggregation) Script(script *Script) *GeoCentroidAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *GeoCentroidAggregation) SubAggregation(name string, subAggregation Aggregation) *GeoCentroidAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *GeoCentroidAggregation) Meta(metaData map[string]interface{}) *GeoCentroidAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *GeoCentroidAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//     \"query\" : {\n\t//         \"match\" : { \"business_type\" : \"shop\" }\n\t//     },\n\t//     \"aggs\" : {\n\t//\t\t\t\"centroid\" : {\n\t//\t\t\t\t\"geo_centroid\" : {\n\t//\t\t\t\t\t\"field\" : \"location\"\n\t//\t\t\t\t}\n\t//\t\t\t}\n\t//\t\t}\n\t// }\n\t//\n\t// This method returns only the { \"geo_centroid\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"geo_centroid\"] = opts\n\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_geo_centroid_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGeoCentroidAggregation(t *testing.T) {\n\tagg := NewGeoCentroidAggregation().Field(\"location\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_centroid\":{\"field\":\"location\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoCentroidAggregationWithMetaData(t *testing.T) {\n\tagg := NewGeoCentroidAggregation().Field(\"location\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_centroid\":{\"field\":\"location\"},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_max.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MaxAggregation is a single-value metrics aggregation that keeps track and\n// returns the maximum value among the numeric values extracted from\n// the aggregated documents. These values can be extracted either from\n// specific numeric fields in the documents, or be generated by\n// a provided script.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-max-aggregation.html\ntype MaxAggregation struct {\n\tfield           string\n\tscript          *Script\n\tformat          string\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewMaxAggregation() *MaxAggregation {\n\treturn &MaxAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *MaxAggregation) Field(field string) *MaxAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *MaxAggregation) Script(script *Script) *MaxAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *MaxAggregation) Format(format string) *MaxAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *MaxAggregation) Missing(missing interface{}) *MaxAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *MaxAggregation) SubAggregation(name string, subAggregation Aggregation) *MaxAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MaxAggregation) Meta(metaData map[string]interface{}) *MaxAggregation {\n\ta.meta = metaData\n\treturn a\n}\nfunc (a *MaxAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"max_price\" : { \"max\" : { \"field\" : \"price\" } }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"max\" : { \"field\" : \"price\" } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"max\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_max_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMaxAggregation(t *testing.T) {\n\tagg := NewMaxAggregation().Field(\"price\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"max\":{\"field\":\"price\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMaxAggregationWithOptions(t *testing.T) {\n\tagg := NewMaxAggregation().\n\t\tField(\"price\").\n\t\tFormat(\"00000.00\").\n\t\tMissing(1.2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"max\":{\"field\":\"price\",\"format\":\"00000.00\",\"missing\":1.2}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMaxAggregationWithMetaData(t *testing.T) {\n\tagg := NewMaxAggregation().Field(\"price\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"max\":{\"field\":\"price\"},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_median_absolute_deviation.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MedianAbsoluteDeviationAggregation is a measure of variability.\n// It is a robust statistic, meaning that it is useful for describing data\n// that may have outliers, or may not be normally distributed.\n// For such data it can be more descriptive than standard deviation.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.6/search-aggregations-metrics-median-absolute-deviation-aggregation.html\n// for details.\ntype MedianAbsoluteDeviationAggregation struct {\n\tfield           string\n\tcompression     *float64\n\tscript          *Script\n\tformat          string\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewMedianAbsoluteDeviationAggregation() *MedianAbsoluteDeviationAggregation {\n\treturn &MedianAbsoluteDeviationAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *MedianAbsoluteDeviationAggregation) Field(field string) *MedianAbsoluteDeviationAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *MedianAbsoluteDeviationAggregation) Compression(compression float64) *MedianAbsoluteDeviationAggregation {\n\ta.compression = &compression\n\treturn a\n}\n\nfunc (a *MedianAbsoluteDeviationAggregation) Script(script *Script) *MedianAbsoluteDeviationAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *MedianAbsoluteDeviationAggregation) Format(format string) *MedianAbsoluteDeviationAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *MedianAbsoluteDeviationAggregation) Missing(missing interface{}) *MedianAbsoluteDeviationAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *MedianAbsoluteDeviationAggregation) SubAggregation(name string, subAggregation Aggregation) *MedianAbsoluteDeviationAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MedianAbsoluteDeviationAggregation) Meta(metaData map[string]interface{}) *MedianAbsoluteDeviationAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *MedianAbsoluteDeviationAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"review_variability\" : { \"median_absolute_deviation\" : { \"field\" : \"rating\" } }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"median_absolute_deviation\" : { \"field\" : \"rating\" } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"median_absolute_deviation\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif v := a.compression; v != nil {\n\t\topts[\"compression\"] = *v\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_median_absolute_deviation_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMedianAbsoluteDeviationAggregation(t *testing.T) {\n\tagg := NewMedianAbsoluteDeviationAggregation().Field(\"rating\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"median_absolute_deviation\":{\"field\":\"rating\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMedianAbsoluteDeviationAggregationWithOptions(t *testing.T) {\n\tagg := NewMedianAbsoluteDeviationAggregation().\n\t\tField(\"rating\").\n\t\tCompression(100).\n\t\tMissing(5)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"median_absolute_deviation\":{\"compression\":100,\"field\":\"rating\",\"missing\":5}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMedianAbsoluteDeviationAggregationWithScript(t *testing.T) {\n\tagg := NewMedianAbsoluteDeviationAggregation().\n\t\tScript(\n\t\t\tNewScript(`doc['rating'].value * params.scaleFactor`).\n\t\t\t\tLang(\"painless\").\n\t\t\t\tParam(\"scaleFactor\", 2.0),\n\t\t)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"median_absolute_deviation\":{\"script\":{\"lang\":\"painless\",\"params\":{\"scaleFactor\":2},\"source\":\"doc['rating'].value * params.scaleFactor\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMedianAbsoluteDeviationAggregationWithMetaData(t *testing.T) {\n\tagg := NewMedianAbsoluteDeviationAggregation().Field(\"rating\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"median_absolute_deviation\":{\"field\":\"rating\"},\"meta\":{\"name\":\"Oliver\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_min.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MinAggregation is a single-value metrics aggregation that keeps track and\n// returns the minimum value among numeric values extracted from the\n// aggregated documents. These values can be extracted either from\n// specific numeric fields in the documents, or be generated by a\n// provided script.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-min-aggregation.html\ntype MinAggregation struct {\n\tfield           string\n\tscript          *Script\n\tformat          string\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewMinAggregation() *MinAggregation {\n\treturn &MinAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *MinAggregation) Field(field string) *MinAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *MinAggregation) Script(script *Script) *MinAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *MinAggregation) Format(format string) *MinAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *MinAggregation) Missing(missing interface{}) *MinAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *MinAggregation) SubAggregation(name string, subAggregation Aggregation) *MinAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MinAggregation) Meta(metaData map[string]interface{}) *MinAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *MinAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"min_price\" : { \"min\" : { \"field\" : \"price\" } }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"min\" : { \"field\" : \"price\" } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"min\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_min_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMinAggregation(t *testing.T) {\n\tagg := NewMinAggregation().Field(\"price\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"min\":{\"field\":\"price\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMinAggregationWithOptions(t *testing.T) {\n\tagg := NewMinAggregation().\n\t\tField(\"price\").\n\t\tFormat(\"00000.00\").\n\t\tMissing(1.2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"min\":{\"field\":\"price\",\"format\":\"00000.00\",\"missing\":1.2}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMinAggregationWithMetaData(t *testing.T) {\n\tagg := NewMinAggregation().Field(\"price\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"min\":{\"field\":\"price\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_percentile_ranks.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// PercentileRanksAggregation\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-percentile-rank-aggregation.html\ntype PercentileRanksAggregation struct {\n\tfield           string\n\tscript          *Script\n\tformat          string\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n\tvalues          []float64\n\tcompression     *float64\n\testimator       string\n}\n\nfunc NewPercentileRanksAggregation() *PercentileRanksAggregation {\n\treturn &PercentileRanksAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t\tvalues:          make([]float64, 0),\n\t}\n}\n\nfunc (a *PercentileRanksAggregation) Field(field string) *PercentileRanksAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *PercentileRanksAggregation) Script(script *Script) *PercentileRanksAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *PercentileRanksAggregation) Format(format string) *PercentileRanksAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *PercentileRanksAggregation) Missing(missing interface{}) *PercentileRanksAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *PercentileRanksAggregation) SubAggregation(name string, subAggregation Aggregation) *PercentileRanksAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *PercentileRanksAggregation) Meta(metaData map[string]interface{}) *PercentileRanksAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *PercentileRanksAggregation) Values(values ...float64) *PercentileRanksAggregation {\n\ta.values = append(a.values, values...)\n\treturn a\n}\n\nfunc (a *PercentileRanksAggregation) Compression(compression float64) *PercentileRanksAggregation {\n\ta.compression = &compression\n\treturn a\n}\n\nfunc (a *PercentileRanksAggregation) Estimator(estimator string) *PercentileRanksAggregation {\n\ta.estimator = estimator\n\treturn a\n}\n\nfunc (a *PercentileRanksAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"load_time_outlier\" : {\n\t//         \"percentile_ranks\" : {\n\t//           \"field\" : \"load_time\"\n\t//           \"values\" : [15, 30]\n\t//         }\n\t//       }\n\t//    }\n\t//\t}\n\t// This method returns only the\n\t//   { \"percentile_ranks\" : { \"field\" : \"load_time\", \"values\" : [15, 30] } }\n\t// part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"percentile_ranks\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\tif len(a.values) > 0 {\n\t\topts[\"values\"] = a.values\n\t}\n\tif a.compression != nil {\n\t\topts[\"compression\"] = *a.compression\n\t}\n\tif a.estimator != \"\" {\n\t\topts[\"estimator\"] = a.estimator\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_percentile_ranks_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestPercentileRanksAggregation(t *testing.T) {\n\tagg := NewPercentileRanksAggregation().Field(\"load_time\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentile_ranks\":{\"field\":\"load_time\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercentileRanksAggregationWithCustomValues(t *testing.T) {\n\tagg := NewPercentileRanksAggregation().Field(\"load_time\").Values(15, 30)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentile_ranks\":{\"field\":\"load_time\",\"values\":[15,30]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercentileRanksAggregationWithOptions(t *testing.T) {\n\tagg := NewPercentileRanksAggregation().\n\t\tField(\"load_time\").\n\t\tFormat(\"000.0\").\n\t\tMissing(1.2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentile_ranks\":{\"field\":\"load_time\",\"format\":\"000.0\",\"missing\":1.2}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercentileRanksAggregationWithMetaData(t *testing.T) {\n\tagg := NewPercentileRanksAggregation().Field(\"load_time\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"percentile_ranks\":{\"field\":\"load_time\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_percentiles.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// PercentilesAggregation is a multi-value metrics aggregation\n// that calculates one or more percentiles over numeric values\n// extracted from the aggregated documents. These values can\n// be extracted either from specific numeric fields in the documents,\n// or be generated by a provided script.\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-percentile-aggregation.html\ntype PercentilesAggregation struct {\n\tfield                          string\n\tscript                         *Script\n\tformat                         string\n\tmissing                        interface{}\n\tsubAggregations                map[string]Aggregation\n\tmeta                           map[string]interface{}\n\tpercentiles                    []float64\n\tmethod                         string\n\tcompression                    *float64\n\tnumberOfSignificantValueDigits *int\n\testimator                      string\n}\n\nfunc NewPercentilesAggregation() *PercentilesAggregation {\n\treturn &PercentilesAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t\tpercentiles:     make([]float64, 0),\n\t\tmethod:          \"tdigest\",\n\t}\n}\n\nfunc (a *PercentilesAggregation) Field(field string) *PercentilesAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *PercentilesAggregation) Script(script *Script) *PercentilesAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *PercentilesAggregation) Format(format string) *PercentilesAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *PercentilesAggregation) Missing(missing interface{}) *PercentilesAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *PercentilesAggregation) SubAggregation(name string, subAggregation Aggregation) *PercentilesAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *PercentilesAggregation) Meta(metaData map[string]interface{}) *PercentilesAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *PercentilesAggregation) Percentiles(percentiles ...float64) *PercentilesAggregation {\n\ta.percentiles = append(a.percentiles, percentiles...)\n\treturn a\n}\n\n// Method is the percentiles method, which can be \"tdigest\" (default) or \"hdr\".\nfunc (a *PercentilesAggregation) Method(method string) *PercentilesAggregation {\n\ta.method = method\n\treturn a\n}\n\nfunc (a *PercentilesAggregation) Compression(compression float64) *PercentilesAggregation {\n\ta.compression = &compression\n\treturn a\n}\n\nfunc (a *PercentilesAggregation) NumberOfSignificantValueDigits(digits int) *PercentilesAggregation {\n\ta.numberOfSignificantValueDigits = &digits\n\treturn a\n}\n\nfunc (a *PercentilesAggregation) Estimator(estimator string) *PercentilesAggregation {\n\ta.estimator = estimator\n\treturn a\n}\n\nfunc (a *PercentilesAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"load_time_outlier\" : {\n\t//           \"percentiles\" : {\n\t//               \"field\" : \"load_time\"\n\t//           }\n\t//       }\n\t//    }\n\t//\t}\n\t// This method returns only the\n\t//   { \"percentiles\" : { \"field\" : \"load_time\" } }\n\t// part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"percentiles\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\tif len(a.percentiles) > 0 {\n\t\topts[\"percents\"] = a.percentiles\n\t}\n\tswitch a.method {\n\tcase \"tdigest\":\n\t\tif c := a.compression; c != nil {\n\t\t\topts[a.method] = map[string]interface{}{\n\t\t\t\t\"compression\": *c,\n\t\t\t}\n\t\t}\n\tcase \"hdr\":\n\t\tif n := a.numberOfSignificantValueDigits; n != nil {\n\t\t\topts[a.method] = map[string]interface{}{\n\t\t\t\t\"number_of_significant_value_digits\": *n,\n\t\t\t}\n\t\t}\n\t}\n\tif a.estimator != \"\" {\n\t\topts[\"estimator\"] = a.estimator\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_percentiles_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestPercentilesAggregation(t *testing.T) {\n\tagg := NewPercentilesAggregation().Field(\"price\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentiles\":{\"field\":\"price\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercentilesAggregationWithCustomPercents(t *testing.T) {\n\tagg := NewPercentilesAggregation().Field(\"price\").Percentiles(0.2, 0.5, 0.9)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentiles\":{\"field\":\"price\",\"percents\":[0.2,0.5,0.9]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercentilesAggregationWithOptions(t *testing.T) {\n\tagg := NewPercentilesAggregation().\n\t\tField(\"price\").\n\t\tFormat(\"00000.00\").\n\t\tMissing(1.2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentiles\":{\"field\":\"price\",\"format\":\"00000.00\",\"missing\":1.2}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercentilesAggregationWithMetaData(t *testing.T) {\n\tagg := NewPercentilesAggregation().Field(\"price\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"percentiles\":{\"field\":\"price\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercentilesAggregationWithCompression(t *testing.T) {\n\tagg := NewPercentilesAggregation().Field(\"load_time\").Compression(200.0)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentiles\":{\"field\":\"load_time\",\"tdigest\":{\"compression\":200}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercentilesAggregationWithNumberOfSignificantValueDigits(t *testing.T) {\n\tagg := NewPercentilesAggregation().\n\t\tField(\"load_time\").\n\t\tPercentiles(95, 99, 99.9).\n\t\tMethod(\"hdr\").\n\t\tNumberOfSignificantValueDigits(5)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentiles\":{\"field\":\"load_time\",\"hdr\":{\"number_of_significant_value_digits\":5},\"percents\":[95,99,99.9]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_scripted_metric.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\npackage elastic\n\n// ScriptedMetricAggregation is a a metric aggregation that executes using scripts to provide a metric output.\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-scripted-metric-aggregation.html\ntype ScriptedMetricAggregation struct {\n\tinitScript    *Script\n\tmapScript     *Script\n\tcombineScript *Script\n\treduceScript  *Script\n\n\tparams map[string]interface{}\n\tmeta   map[string]interface{}\n}\n\nfunc NewScriptedMetricAggregation() *ScriptedMetricAggregation {\n\ta := &ScriptedMetricAggregation{}\n\treturn a\n}\n\nfunc (a *ScriptedMetricAggregation) InitScript(script *Script) *ScriptedMetricAggregation {\n\ta.initScript = script\n\treturn a\n}\n\nfunc (a *ScriptedMetricAggregation) MapScript(script *Script) *ScriptedMetricAggregation {\n\ta.mapScript = script\n\treturn a\n}\n\nfunc (a *ScriptedMetricAggregation) CombineScript(script *Script) *ScriptedMetricAggregation {\n\ta.combineScript = script\n\treturn a\n}\n\nfunc (a *ScriptedMetricAggregation) ReduceScript(script *Script) *ScriptedMetricAggregation {\n\ta.reduceScript = script\n\treturn a\n}\n\nfunc (a *ScriptedMetricAggregation) Params(params map[string]interface{}) *ScriptedMetricAggregation {\n\ta.params = params\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *ScriptedMetricAggregation) Meta(metaData map[string]interface{}) *ScriptedMetricAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *ScriptedMetricAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"magic_script\" : { \"scripted_metric\" : {\n\t//  \t\t\"init_script\" : \"state.transactions = []\",\n\t//\t\t  \t\"map_script\" : \"state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)\",\n\t//\t\t  \t\"combine_script\" : \"double profit = 0; for (t in state.transactions) { profit += t } return profit\",\n\t//\t\t  \t\"reduce_script\" : \"double profit = 0; for (a in states) { profit += a } return profit\"\n\t//      } }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"scripted_metric\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"scripted_metric\"] = opts\n\n\tif a.initScript != nil {\n\t\tsrc, err := a.initScript.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"init_script\"] = src\n\t}\n\tif a.mapScript != nil {\n\t\tsrc, err := a.mapScript.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"map_script\"] = src\n\t}\n\tif a.combineScript != nil {\n\t\tsrc, err := a.combineScript.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"combine_script\"] = src\n\t}\n\tif a.reduceScript != nil {\n\t\tsrc, err := a.reduceScript.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"reduce_script\"] = src\n\t}\n\n\tif a.params != nil && len(a.params) > 0 {\n\t\topts[\"params\"] = a.params\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_scripted_metric_test.go",
    "content": "package elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestScriptedMetricAggregation(t *testing.T) {\n\tagg := NewScriptedMetricAggregation().\n\t\tInitScript(NewScript(\"state.transactions = []\")).\n\t\tMapScript(NewScript(\"state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)\")).\n\t\tCombineScript(NewScript(\"double profit = 0; for (t in state.transactions) { profit += t } return profit\")).\n\t\tReduceScript(NewScript(\"double profit = 0; for (a in states) { profit += a } return profit\"))\n\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"scripted_metric\":{\"combine_script\":{\"source\":\"double profit = 0; for (t in state.transactions) { profit += t } return profit\"},\"init_script\":{\"source\":\"state.transactions = []\"},\"map_script\":{\"source\":\"state.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)\"},\"reduce_script\":{\"source\":\"double profit = 0; for (a in states) { profit += a } return profit\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScriptedMetricAggregationWithParams(t *testing.T) {\n\tagg := NewScriptedMetricAggregation().\n\t\tMapScript(NewScript(\"r=0;\")).\n\t\tReduceScript(NewScript(\"return params.a;\")).\n\t\tParams(map[string]interface{}{\"a\": 3})\n\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"scripted_metric\":{\"map_script\":{\"source\":\"r=0;\"},\"params\":{\"a\":3},\"reduce_script\":{\"source\":\"return params.a;\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScriptedMetricAggregationWithMeta(t *testing.T) {\n\tagg := NewScriptedMetricAggregation().\n\t\tMapScript(NewScript(\"r=0;\")).\n\t\tReduceScript(NewScript(\"return params.a;\")).\n\t\tMeta(map[string]interface{}{\"foo\": \"bar\"})\n\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"foo\":\"bar\"},\"scripted_metric\":{\"map_script\":{\"source\":\"r=0;\"},\"reduce_script\":{\"source\":\"return params.a;\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_stats.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// StatsAggregation is a multi-value metrics aggregation that computes stats\n// over numeric values extracted from the aggregated documents.\n// These values can be extracted either from specific numeric fields\n// in the documents, or be generated by a provided script.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-stats-aggregation.html\ntype StatsAggregation struct {\n\tfield           string\n\tscript          *Script\n\tformat          string\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewStatsAggregation() *StatsAggregation {\n\treturn &StatsAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *StatsAggregation) Field(field string) *StatsAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *StatsAggregation) Script(script *Script) *StatsAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *StatsAggregation) Format(format string) *StatsAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *StatsAggregation) Missing(missing interface{}) *StatsAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *StatsAggregation) SubAggregation(name string, subAggregation Aggregation) *StatsAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *StatsAggregation) Meta(metaData map[string]interface{}) *StatsAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *StatsAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"grades_stats\" : { \"stats\" : { \"field\" : \"grade\" } }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"stats\" : { \"field\" : \"grade\" } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"stats\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_stats_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestStatsAggregation(t *testing.T) {\n\tagg := NewStatsAggregation().Field(\"grade\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"stats\":{\"field\":\"grade\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestStatsAggregationWithOptions(t *testing.T) {\n\tagg := NewStatsAggregation().\n\t\tField(\"grade\").\n\t\tFormat(\"0000.0\").\n\t\tMissing(1.2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"stats\":{\"field\":\"grade\",\"format\":\"0000.0\",\"missing\":1.2}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestStatsAggregationWithMetaData(t *testing.T) {\n\tagg := NewStatsAggregation().Field(\"grade\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"stats\":{\"field\":\"grade\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_sum.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SumAggregation is a single-value metrics aggregation that sums up\n// numeric values that are extracted from the aggregated documents.\n// These values can be extracted either from specific numeric fields\n// in the documents, or be generated by a provided script.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-sum-aggregation.html\ntype SumAggregation struct {\n\tfield           string\n\tscript          *Script\n\tformat          string\n\tmissing         interface{}\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewSumAggregation() *SumAggregation {\n\treturn &SumAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *SumAggregation) Field(field string) *SumAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *SumAggregation) Script(script *Script) *SumAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *SumAggregation) Format(format string) *SumAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *SumAggregation) Missing(missing interface{}) *SumAggregation {\n\ta.missing = missing\n\treturn a\n}\n\nfunc (a *SumAggregation) SubAggregation(name string, subAggregation Aggregation) *SumAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *SumAggregation) Meta(metaData map[string]interface{}) *SumAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *SumAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"intraday_return\" : { \"sum\" : { \"field\" : \"change\" } }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"sum\" : { \"field\" : \"change\" } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"sum\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\tif a.missing != nil {\n\t\topts[\"missing\"] = a.missing\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_sum_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSumAggregation(t *testing.T) {\n\tagg := NewSumAggregation().Field(\"price\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"sum\":{\"field\":\"price\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSumAggregationWithOptions(t *testing.T) {\n\tagg := NewSumAggregation().\n\t\tField(\"price\").\n\t\tFormat(\"00000.00\").\n\t\tMissing(1.2)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"sum\":{\"field\":\"price\",\"format\":\"00000.00\",\"missing\":1.2}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSumAggregationWithMetaData(t *testing.T) {\n\tagg := NewSumAggregation().Field(\"price\").Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"sum\":{\"field\":\"price\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_top_hits.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// TopHitsAggregation keeps track of the most relevant document\n// being aggregated. This aggregator is intended to be used as a\n// sub aggregator, so that the top matching documents\n// can be aggregated per bucket.\n//\n// It can effectively be used to group result sets by certain fields via\n// a bucket aggregator. One or more bucket aggregators determines by\n// which properties a result set get sliced into.\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-top-hits-aggregation.html\ntype TopHitsAggregation struct {\n\tsearchSource *SearchSource\n}\n\nfunc NewTopHitsAggregation() *TopHitsAggregation {\n\treturn &TopHitsAggregation{\n\t\tsearchSource: NewSearchSource(),\n\t}\n}\n\nfunc (a *TopHitsAggregation) SearchSource(searchSource *SearchSource) *TopHitsAggregation {\n\ta.searchSource = searchSource\n\tif a.searchSource == nil {\n\t\ta.searchSource = NewSearchSource()\n\t}\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) From(from int) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.From(from)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) Size(size int) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.Size(size)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) TrackScores(trackScores bool) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.TrackScores(trackScores)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) Explain(explain bool) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.Explain(explain)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) Version(version bool) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.Version(version)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) NoStoredFields() *TopHitsAggregation {\n\ta.searchSource = a.searchSource.NoStoredFields()\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) FetchSource(fetchSource bool) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.FetchSource(fetchSource)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) FetchSourceContext(fetchSourceContext *FetchSourceContext) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.FetchSourceContext(fetchSourceContext)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) DocvalueFields(docvalueFields ...string) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.DocvalueFields(docvalueFields...)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) DocvalueFieldsWithFormat(docvalueFields ...DocvalueField) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.DocvalueFieldsWithFormat(docvalueFields...)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) DocvalueField(docvalueField string) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.DocvalueField(docvalueField)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) DocvalueFieldWithFormat(docvalueField DocvalueField) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.DocvalueFieldWithFormat(docvalueField)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) ScriptFields(scriptFields ...*ScriptField) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.ScriptFields(scriptFields...)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) ScriptField(scriptField *ScriptField) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.ScriptField(scriptField)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) Sort(field string, ascending bool) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.Sort(field, ascending)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) SortWithInfo(info SortInfo) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.SortWithInfo(info)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) SortBy(sorter ...Sorter) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.SortBy(sorter...)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) Highlight(highlight *Highlight) *TopHitsAggregation {\n\ta.searchSource = a.searchSource.Highlight(highlight)\n\treturn a\n}\n\nfunc (a *TopHitsAggregation) Highlighter() *Highlight {\n\treturn a.searchSource.Highlighter()\n}\n\nfunc (a *TopHitsAggregation) Source() (interface{}, error) {\n\t// Example:\n\t// {\n\t//   \"aggs\": {\n\t//       \"top_tag_hits\": {\n\t//           \"top_hits\": {\n\t//               \"sort\": [\n\t//                   {\n\t//                       \"last_activity_date\": {\n\t//                           \"order\": \"desc\"\n\t//                       }\n\t//                   }\n\t//               ],\n\t//               \"_source\": {\n\t//                   \"include\": [\n\t//                       \"title\"\n\t//                   ]\n\t//               },\n\t//               \"size\" : 1\n\t//           }\n\t//       }\n\t//   }\n\t// }\n\t// This method returns only the { \"top_hits\" : { ... } } part.\n\n\tsource := make(map[string]interface{})\n\tsrc, err := a.searchSource.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsource[\"top_hits\"] = src\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_top_hits_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestTopHitsAggregation(t *testing.T) {\n\tfsc := NewFetchSourceContext(true).Include(\"title\")\n\tagg := NewTopHitsAggregation().\n\t\tSort(\"last_activity_date\", false).\n\t\tFetchSourceContext(fsc).\n\t\tSize(1)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"top_hits\":{\"_source\":{\"includes\":[\"title\"]},\"size\":1,\"sort\":[{\"last_activity_date\":{\"order\":\"desc\"}}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_top_metrics.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"errors\"\n\n// TopMetricsAggregation selects metrics from the document with the largest or smallest \"sort\" value.\n// top_metrics is fairly similar to top_hits in spirit but because it is more limited it is able to do\n// its job using less memory and is often faster.\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-top-metrics.html\ntype TopMetricsAggregation struct {\n\tfields []string\n\tsorter Sorter\n\tsize   int\n}\n\nfunc NewTopMetricsAggregation() *TopMetricsAggregation {\n\treturn &TopMetricsAggregation{}\n}\n\n// Field adds a field to run aggregation against.\nfunc (a *TopMetricsAggregation) Field(field string) *TopMetricsAggregation {\n\ta.fields = append(a.fields, field)\n\treturn a\n}\n\n// Sort adds a sort order.\nfunc (a *TopMetricsAggregation) Sort(field string, ascending bool) *TopMetricsAggregation {\n\ta.sorter = SortInfo{Field: field, Ascending: ascending}\n\treturn a\n}\n\n// SortWithInfo adds a sort order.\nfunc (a *TopMetricsAggregation) SortWithInfo(info SortInfo) *TopMetricsAggregation {\n\ta.sorter = info\n\treturn a\n}\n\n// SortBy adds a sort order.\nfunc (a *TopMetricsAggregation) SortBy(sorter Sorter) *TopMetricsAggregation {\n\ta.sorter = sorter\n\treturn a\n}\n\n// Size sets the number of top documents returned by the aggregation. The default size is 1.\nfunc (a *TopMetricsAggregation) Size(size int) *TopMetricsAggregation {\n\ta.size = size\n\treturn a\n}\n\nfunc (a *TopMetricsAggregation) Source() (interface{}, error) {\n\tparams := make(map[string]interface{})\n\n\tif len(a.fields) == 0 {\n\t\treturn nil, errors.New(\"field list is required for the top metrics aggregation\")\n\t}\n\tmetrics := make([]interface{}, len(a.fields))\n\tfor idx, field := range a.fields {\n\t\tmetrics[idx] = map[string]string{\"field\": field}\n\t}\n\tparams[\"metrics\"] = metrics\n\n\tif a.sorter == nil {\n\t\treturn nil, errors.New(\"sorter is required for the top metrics aggregation\")\n\t}\n\tsortSource, err := a.sorter.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tparams[\"sort\"] = sortSource\n\n\tif a.size > 1 {\n\t\tparams[\"size\"] = a.size\n\t}\n\n\tsource := map[string]interface{}{\n\t\t\"top_metrics\": params,\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_top_metrics_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestTopMetricsAggregation(t *testing.T) {\n\tagg := NewTopMetricsAggregation().\n\t\tSort(\"f1\", false).\n\t\tField(\"a\").\n\t\tField(\"b\").\n\t\tSize(3)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"top_metrics\":{\"metrics\":[{\"field\":\"a\"},{\"field\":\"b\"}],\"size\":3,\"sort\":{\"f1\":{\"order\":\"desc\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTopMetricsAggregation_SortBy(t *testing.T) {\n\tagg := NewTopMetricsAggregation().\n\t\tSortBy(SortByDoc{}).\n\t\tField(\"a\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"top_metrics\":{\"metrics\":[{\"field\":\"a\"}],\"sort\":\"_doc\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTopMetricsAggregation_SortWithInfo(t *testing.T) {\n\tagg := NewTopMetricsAggregation().\n\t\tSortWithInfo(SortInfo{Field: \"f2\", Ascending: true, UnmappedType: \"int\"}).\n\t\tField(\"b\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"top_metrics\":{\"metrics\":[{\"field\":\"b\"}],\"sort\":{\"f2\":{\"order\":\"asc\",\"unmapped_type\":\"int\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTopMetricsAggregation_FailNoSorter(t *testing.T) {\n\tagg := NewTopMetricsAggregation().\n\t\tField(\"a\").\n\t\tField(\"b\")\n\t_, err := agg.Source()\n\tif err == nil || err.Error() != \"sorter is required for the top metrics aggregation\" {\n\t\tt.Fatal(err)\n\t}\n}\n\nfunc TestTopMetricsAggregation_FailNoFields(t *testing.T) {\n\tagg := NewTopMetricsAggregation().\n\t\tSort(\"f1\", false)\n\t_, err := agg.Source()\n\tif err == nil || err.Error() != \"field list is required for the top metrics aggregation\" {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_value_count.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// ValueCountAggregation is a single-value metrics aggregation that counts\n// the number of values that are extracted from the aggregated documents.\n// These values can be extracted either from specific fields in the documents,\n// or be generated by a provided script. Typically, this aggregator will be\n// used in conjunction with other single-value aggregations.\n// For example, when computing the avg one might be interested in the\n// number of values the average is computed over.\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-valuecount-aggregation.html\ntype ValueCountAggregation struct {\n\tfield           string\n\tscript          *Script\n\tformat          string\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewValueCountAggregation() *ValueCountAggregation {\n\treturn &ValueCountAggregation{\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *ValueCountAggregation) Field(field string) *ValueCountAggregation {\n\ta.field = field\n\treturn a\n}\n\nfunc (a *ValueCountAggregation) Script(script *Script) *ValueCountAggregation {\n\ta.script = script\n\treturn a\n}\n\nfunc (a *ValueCountAggregation) Format(format string) *ValueCountAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *ValueCountAggregation) SubAggregation(name string, subAggregation Aggregation) *ValueCountAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *ValueCountAggregation) Meta(metaData map[string]interface{}) *ValueCountAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *ValueCountAggregation) Source() (interface{}, error) {\n\t// Example:\n\t//\t{\n\t//    \"aggs\" : {\n\t//      \"grades_count\" : { \"value_count\" : { \"field\" : \"grade\" } }\n\t//    }\n\t//\t}\n\t// This method returns only the { \"value_count\" : { \"field\" : \"grade\" } } part.\n\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"value_count\"] = opts\n\n\t// ValuesSourceAggregationBuilder\n\tif a.field != \"\" {\n\t\topts[\"field\"] = a.field\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"script\"] = src\n\t}\n\tif a.format != \"\" {\n\t\topts[\"format\"] = a.format\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_value_count_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestValueCountAggregation(t *testing.T) {\n\tagg := NewValueCountAggregation().Field(\"grade\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"value_count\":{\"field\":\"grade\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestValueCountAggregationWithFormat(t *testing.T) {\n\t// Format comes with 1.5.0+\n\tagg := NewValueCountAggregation().Field(\"grade\").Format(\"0000.0\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"value_count\":{\"field\":\"grade\",\"format\":\"0000.0\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestValueCountAggregationWithMetaData(t *testing.T) {\n\tagg := NewValueCountAggregation().Field(\"grade\")\n\tagg = agg.Meta(map[string]interface{}{\"name\": \"Oliver\"})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"meta\":{\"name\":\"Oliver\"},\"value_count\":{\"field\":\"grade\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_metrics_weighted_avg.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// WeightedAvgAggregation is a single-value metrics aggregation that\n// computes the weighted average of numeric values that are extracted\n// from the aggregated documents. These values can be extracted either\n// from specific numeric fields in the documents.\n//\n// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-metrics-weight-avg-aggregation.html\ntype WeightedAvgAggregation struct {\n\tfields          map[string]*MultiValuesSourceFieldConfig\n\tvalueType       string\n\tformat          string\n\tvalue           *MultiValuesSourceFieldConfig\n\tweight          *MultiValuesSourceFieldConfig\n\tsubAggregations map[string]Aggregation\n\tmeta            map[string]interface{}\n}\n\nfunc NewWeightedAvgAggregation() *WeightedAvgAggregation {\n\treturn &WeightedAvgAggregation{\n\t\tfields:          make(map[string]*MultiValuesSourceFieldConfig),\n\t\tsubAggregations: make(map[string]Aggregation),\n\t}\n}\n\nfunc (a *WeightedAvgAggregation) Field(field string, config *MultiValuesSourceFieldConfig) *WeightedAvgAggregation {\n\ta.fields[field] = config\n\treturn a\n}\n\nfunc (a *WeightedAvgAggregation) ValueType(valueType string) *WeightedAvgAggregation {\n\ta.valueType = valueType\n\treturn a\n}\n\nfunc (a *WeightedAvgAggregation) Format(format string) *WeightedAvgAggregation {\n\ta.format = format\n\treturn a\n}\n\nfunc (a *WeightedAvgAggregation) Value(value *MultiValuesSourceFieldConfig) *WeightedAvgAggregation {\n\ta.value = value\n\treturn a\n}\n\nfunc (a *WeightedAvgAggregation) Weight(weight *MultiValuesSourceFieldConfig) *WeightedAvgAggregation {\n\ta.weight = weight\n\treturn a\n}\n\nfunc (a *WeightedAvgAggregation) SubAggregation(name string, subAggregation Aggregation) *WeightedAvgAggregation {\n\ta.subAggregations[name] = subAggregation\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *WeightedAvgAggregation) Meta(metaData map[string]interface{}) *WeightedAvgAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\nfunc (a *WeightedAvgAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\topts := make(map[string]interface{})\n\tsource[\"weighted_avg\"] = opts\n\n\tif len(a.fields) > 0 {\n\t\tf := make(map[string]interface{})\n\t\tfor name, config := range a.fields {\n\t\t\tcfg, err := config.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tf[name] = cfg\n\t\t}\n\t\topts[\"fields\"] = f\n\t}\n\n\tif v := a.format; v != \"\" {\n\t\topts[\"format\"] = v\n\t}\n\n\tif v := a.valueType; v != \"\" {\n\t\topts[\"value_type\"] = v\n\t}\n\n\tif v := a.value; v != nil {\n\t\tcfg, err := v.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"value\"] = cfg\n\t}\n\n\tif v := a.weight; v != nil {\n\t\tcfg, err := v.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\topts[\"weight\"] = cfg\n\t}\n\n\t// AggregationBuilder (SubAggregations)\n\tif len(a.subAggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tsource[\"aggregations\"] = aggsMap\n\t\tfor name, aggregate := range a.subAggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n\n// MultiValuesSourceFieldConfig represents a field configuration\n// used e.g. in WeightedAvgAggregation.\ntype MultiValuesSourceFieldConfig struct {\n\tFieldName string\n\tMissing   interface{}\n\tScript    *Script\n\tTimeZone  string\n}\n\nfunc (f *MultiValuesSourceFieldConfig) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif v := f.Missing; v != nil {\n\t\tsource[\"missing\"] = v\n\t}\n\tif v := f.Script; v != nil {\n\t\tsrc, err := v.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"script\"] = src\n\t}\n\tif v := f.FieldName; v != \"\" {\n\t\tsource[\"field\"] = v\n\t}\n\tif v := f.TimeZone; v != \"\" {\n\t\tsource[\"time_zone\"] = v\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_metrics_weighted_avg_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestWeightedAvgAggregation(t *testing.T) {\n\tagg := NewWeightedAvgAggregation().\n\t\tValue(&MultiValuesSourceFieldConfig{\n\t\t\tFieldName: \"grade\",\n\t\t}).\n\t\tWeight(&MultiValuesSourceFieldConfig{\n\t\t\tFieldName: \"weight\",\n\t\t\tMissing:   3,\n\t\t})\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"weighted_avg\":{\"value\":{\"field\":\"grade\"},\"weight\":{\"field\":\"weight\",\"missing\":3}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_avg_bucket.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// AvgBucketAggregation is a sibling pipeline aggregation which calculates\n// the (mean) average value of a specified metric in a sibling aggregation.\n// The specified metric must be numeric and the sibling aggregation must\n// be a multi-bucket aggregation.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-avg-bucket-aggregation.html\ntype AvgBucketAggregation struct {\n\tformat    string\n\tgapPolicy string\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewAvgBucketAggregation creates and initializes a new AvgBucketAggregation.\nfunc NewAvgBucketAggregation() *AvgBucketAggregation {\n\treturn &AvgBucketAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *AvgBucketAggregation) Format(format string) *AvgBucketAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *AvgBucketAggregation) GapPolicy(gapPolicy string) *AvgBucketAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *AvgBucketAggregation) GapInsertZeros() *AvgBucketAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *AvgBucketAggregation) GapSkip() *AvgBucketAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *AvgBucketAggregation) Meta(metaData map[string]interface{}) *AvgBucketAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *AvgBucketAggregation) BucketsPath(bucketsPaths ...string) *AvgBucketAggregation {\n\ta.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *AvgBucketAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"avg_bucket\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\n\t// Add buckets paths\n\tswitch len(a.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_avg_bucket_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestAvgBucketAggregation(t *testing.T) {\n\tagg := NewAvgBucketAggregation().BucketsPath(\"the_sum\").GapPolicy(\"skip\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"avg_bucket\":{\"buckets_path\":\"the_sum\",\"gap_policy\":\"skip\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_bucket_script.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// BucketScriptAggregation is a parent pipeline aggregation which executes\n// a script which can perform per bucket computations on specified metrics\n// in the parent multi-bucket aggregation. The specified metric must be\n// numeric and the script must return a numeric value.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-bucket-script-aggregation.html\ntype BucketScriptAggregation struct {\n\tformat    string\n\tgapPolicy string\n\tscript    *Script\n\n\tmeta            map[string]interface{}\n\tbucketsPathsMap map[string]string\n}\n\n// NewBucketScriptAggregation creates and initializes a new BucketScriptAggregation.\nfunc NewBucketScriptAggregation() *BucketScriptAggregation {\n\treturn &BucketScriptAggregation{\n\t\tbucketsPathsMap: make(map[string]string),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *BucketScriptAggregation) Format(format string) *BucketScriptAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *BucketScriptAggregation) GapPolicy(gapPolicy string) *BucketScriptAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *BucketScriptAggregation) GapInsertZeros() *BucketScriptAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *BucketScriptAggregation) GapSkip() *BucketScriptAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Script is the script to run.\nfunc (a *BucketScriptAggregation) Script(script *Script) *BucketScriptAggregation {\n\ta.script = script\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *BucketScriptAggregation) Meta(metaData map[string]interface{}) *BucketScriptAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPathsMap sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *BucketScriptAggregation) BucketsPathsMap(bucketsPathsMap map[string]string) *BucketScriptAggregation {\n\ta.bucketsPathsMap = bucketsPathsMap\n\treturn a\n}\n\n// AddBucketsPath adds a bucket path to use for this pipeline aggregator.\nfunc (a *BucketScriptAggregation) AddBucketsPath(name, path string) *BucketScriptAggregation {\n\tif a.bucketsPathsMap == nil {\n\t\ta.bucketsPathsMap = make(map[string]string)\n\t}\n\ta.bucketsPathsMap[name] = path\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *BucketScriptAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"bucket_script\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tparams[\"script\"] = src\n\t}\n\n\t// Add buckets paths\n\tif len(a.bucketsPathsMap) > 0 {\n\t\tparams[\"buckets_path\"] = a.bucketsPathsMap\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_bucket_script_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestBucketScriptAggregation(t *testing.T) {\n\tagg := NewBucketScriptAggregation().\n\t\tAddBucketsPath(\"tShirtSales\", \"t-shirts>sales\").\n\t\tAddBucketsPath(\"totalSales\", \"total_sales\").\n\t\tScript(NewScript(\"tShirtSales / totalSales * 100\"))\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"bucket_script\":{\"buckets_path\":{\"tShirtSales\":\"t-shirts\\u003esales\",\"totalSales\":\"total_sales\"},\"script\":{\"source\":\"tShirtSales / totalSales * 100\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_bucket_selector.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// BucketSelectorAggregation is a parent pipeline aggregation which\n// determines whether the current bucket will be retained in the parent\n// multi-bucket aggregation. The specific metric must be numeric and\n// the script must return a boolean value. If the script language is\n// expression then a numeric return value is permitted. In this case 0.0\n// will be evaluated as false and all other values will evaluate to true.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-bucket-selector-aggregation.html\ntype BucketSelectorAggregation struct {\n\tformat    string\n\tgapPolicy string\n\tscript    *Script\n\n\tmeta            map[string]interface{}\n\tbucketsPathsMap map[string]string\n}\n\n// NewBucketSelectorAggregation creates and initializes a new BucketSelectorAggregation.\nfunc NewBucketSelectorAggregation() *BucketSelectorAggregation {\n\treturn &BucketSelectorAggregation{\n\t\tbucketsPathsMap: make(map[string]string),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *BucketSelectorAggregation) Format(format string) *BucketSelectorAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *BucketSelectorAggregation) GapPolicy(gapPolicy string) *BucketSelectorAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *BucketSelectorAggregation) GapInsertZeros() *BucketSelectorAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *BucketSelectorAggregation) GapSkip() *BucketSelectorAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Script is the script to run.\nfunc (a *BucketSelectorAggregation) Script(script *Script) *BucketSelectorAggregation {\n\ta.script = script\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *BucketSelectorAggregation) Meta(metaData map[string]interface{}) *BucketSelectorAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPathsMap sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *BucketSelectorAggregation) BucketsPathsMap(bucketsPathsMap map[string]string) *BucketSelectorAggregation {\n\ta.bucketsPathsMap = bucketsPathsMap\n\treturn a\n}\n\n// AddBucketsPath adds a bucket path to use for this pipeline aggregator.\nfunc (a *BucketSelectorAggregation) AddBucketsPath(name, path string) *BucketSelectorAggregation {\n\tif a.bucketsPathsMap == nil {\n\t\ta.bucketsPathsMap = make(map[string]string)\n\t}\n\ta.bucketsPathsMap[name] = path\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *BucketSelectorAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"bucket_selector\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tparams[\"script\"] = src\n\t}\n\n\t// Add buckets paths\n\tif len(a.bucketsPathsMap) > 0 {\n\t\tparams[\"buckets_path\"] = a.bucketsPathsMap\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_bucket_selector_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestBucketSelectorAggregation(t *testing.T) {\n\tagg := NewBucketSelectorAggregation().\n\t\tAddBucketsPath(\"totalSales\", \"total_sales\").\n\t\tScript(NewScript(\"totalSales >= 1000\"))\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"bucket_selector\":{\"buckets_path\":{\"totalSales\":\"total_sales\"},\"script\":{\"source\":\"totalSales \\u003e= 1000\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_bucket_sort.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// BucketSortAggregation parent pipeline aggregation which sorts the buckets\n// of its parent multi-bucket aggregation. Zero or more sort fields may be\n// specified together with the corresponding sort order. Each bucket may be\n// sorted based on its _key, _count or its sub-aggregations. In addition,\n// parameters from and size may be set in order to truncate the result buckets.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-bucket-sort-aggregation.html\ntype BucketSortAggregation struct {\n\tsorters   []Sorter\n\tfrom      int\n\tsize      int\n\tgapPolicy string\n\n\tmeta map[string]interface{}\n}\n\n// NewBucketSortAggregation creates and initializes a new BucketSortAggregation.\nfunc NewBucketSortAggregation() *BucketSortAggregation {\n\treturn &BucketSortAggregation{\n\t\tsize: -1,\n\t}\n}\n\n// Sort adds a sort order to the list of sorters.\nfunc (a *BucketSortAggregation) Sort(field string, ascending bool) *BucketSortAggregation {\n\ta.sorters = append(a.sorters, SortInfo{Field: field, Ascending: ascending})\n\treturn a\n}\n\n// SortWithInfo adds a SortInfo to the list of sorters.\nfunc (a *BucketSortAggregation) SortWithInfo(info SortInfo) *BucketSortAggregation {\n\ta.sorters = append(a.sorters, info)\n\treturn a\n}\n\n// From adds the \"from\" parameter to the aggregation.\nfunc (a *BucketSortAggregation) From(from int) *BucketSortAggregation {\n\ta.from = from\n\treturn a\n}\n\n// Size adds the \"size\" parameter to the aggregation.\nfunc (a *BucketSortAggregation) Size(size int) *BucketSortAggregation {\n\ta.size = size\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"skip\".\nfunc (a *BucketSortAggregation) GapPolicy(gapPolicy string) *BucketSortAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *BucketSortAggregation) GapInsertZeros() *BucketSortAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *BucketSortAggregation) GapSkip() *BucketSortAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Meta sets the meta data in the aggregation.\n// Although metadata is supported for this aggregation by Elasticsearch, it's important to\n// note that there's no use to it because this aggregation does not include new data in the\n// response. It merely reorders parent buckets.\nfunc (a *BucketSortAggregation) Meta(meta map[string]interface{}) *BucketSortAggregation {\n\ta.meta = meta\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *BucketSortAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"bucket_sort\"] = params\n\n\tif a.from != 0 {\n\t\tparams[\"from\"] = a.from\n\t}\n\tif a.size != -1 {\n\t\tparams[\"size\"] = a.size\n\t}\n\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\n\t// Parses sorters to JSON-serializable interface.\n\tif len(a.sorters) > 0 {\n\t\tsorters := make([]interface{}, len(a.sorters))\n\t\tparams[\"sort\"] = sorters\n\t\tfor idx, sorter := range a.sorters {\n\t\t\tsrc, err := sorter.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tsorters[idx] = src\n\t\t}\n\t}\n\n\t// Add metadata if available.\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_bucket_sort_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestBuckerSortAggregation(t *testing.T) {\n\tagg := NewBucketSortAggregation().\n\t\tFrom(2).\n\t\tSize(5).\n\t\tGapInsertZeros().\n\t\tSort(\"sort_field_1\", true).\n\t\tSortWithInfo(SortInfo{Field: \"sort_field_2\", Ascending: false})\n\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"bucket_sort\":{\"from\":2,\"gap_policy\":\"insert_zeros\",\"size\":5,\"sort\":[{\"sort_field_1\":{\"order\":\"asc\"}},{\"sort_field_2\":{\"order\":\"desc\"}}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_cumulative_sum.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// CumulativeSumAggregation is a parent pipeline aggregation which calculates\n// the cumulative sum of a specified metric in a parent histogram (or date_histogram)\n// aggregation. The specified metric must be numeric and the enclosing\n// histogram must have min_doc_count set to 0 (default for histogram aggregations).\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-cumulative-sum-aggregation.html\ntype CumulativeSumAggregation struct {\n\tformat string\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewCumulativeSumAggregation creates and initializes a new CumulativeSumAggregation.\nfunc NewCumulativeSumAggregation() *CumulativeSumAggregation {\n\treturn &CumulativeSumAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *CumulativeSumAggregation) Format(format string) *CumulativeSumAggregation {\n\ta.format = format\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *CumulativeSumAggregation) Meta(metaData map[string]interface{}) *CumulativeSumAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *CumulativeSumAggregation) BucketsPath(bucketsPaths ...string) *CumulativeSumAggregation {\n\ta.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *CumulativeSumAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"cumulative_sum\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\n\t// Add buckets paths\n\tswitch len(a.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_cumulative_sum_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestCumulativeSumAggregation(t *testing.T) {\n\tagg := NewCumulativeSumAggregation().BucketsPath(\"sales\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"cumulative_sum\":{\"buckets_path\":\"sales\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_derivative.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// DerivativeAggregation is a parent pipeline aggregation which calculates\n// the derivative of a specified metric in a parent histogram (or date_histogram)\n// aggregation. The specified metric must be numeric and the enclosing\n// histogram must have min_doc_count set to 0 (default for histogram aggregations).\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-derivative-aggregation.html\ntype DerivativeAggregation struct {\n\tformat    string\n\tgapPolicy string\n\tunit      string\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewDerivativeAggregation creates and initializes a new DerivativeAggregation.\nfunc NewDerivativeAggregation() *DerivativeAggregation {\n\treturn &DerivativeAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *DerivativeAggregation) Format(format string) *DerivativeAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *DerivativeAggregation) GapPolicy(gapPolicy string) *DerivativeAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *DerivativeAggregation) GapInsertZeros() *DerivativeAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *DerivativeAggregation) GapSkip() *DerivativeAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Unit sets the unit provided, e.g. \"1d\" or \"1y\".\n// It is only useful when calculating the derivative using a date_histogram.\nfunc (a *DerivativeAggregation) Unit(unit string) *DerivativeAggregation {\n\ta.unit = unit\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *DerivativeAggregation) Meta(metaData map[string]interface{}) *DerivativeAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *DerivativeAggregation) BucketsPath(bucketsPaths ...string) *DerivativeAggregation {\n\ta.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *DerivativeAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"derivative\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\tif a.unit != \"\" {\n\t\tparams[\"unit\"] = a.unit\n\t}\n\n\t// Add buckets paths\n\tswitch len(a.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_derivative_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestDerivativeAggregation(t *testing.T) {\n\tagg := NewDerivativeAggregation().BucketsPath(\"sales\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"derivative\":{\"buckets_path\":\"sales\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_extended_stats_bucket.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// ExtendedStatsBucketAggregation is a sibling pipeline aggregation which calculates\n// a variety of stats across all bucket of a specified metric in a sibling aggregation.\n// The specified metric must be numeric and the sibling aggregation must\n// be a multi-bucket aggregation.\n//\n// This aggregation provides a few more statistics (sum of squares, standard deviation, etc)\n// compared to the stats_bucket aggregation.\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-extended-stats-bucket-aggregation.html\ntype ExtendedStatsBucketAggregation struct {\n\tformat       string\n\tgapPolicy    string\n\tsigma        *float32\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewExtendedStatsBucketAggregation creates and initializes a new ExtendedStatsBucketAggregation.\nfunc NewExtendedStatsBucketAggregation() *ExtendedStatsBucketAggregation {\n\treturn &ExtendedStatsBucketAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (s *ExtendedStatsBucketAggregation) Format(format string) *ExtendedStatsBucketAggregation {\n\ts.format = format\n\treturn s\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (s *ExtendedStatsBucketAggregation) GapPolicy(gapPolicy string) *ExtendedStatsBucketAggregation {\n\ts.gapPolicy = gapPolicy\n\treturn s\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (s *ExtendedStatsBucketAggregation) GapInsertZeros() *ExtendedStatsBucketAggregation {\n\ts.gapPolicy = \"insert_zeros\"\n\treturn s\n}\n\n// GapSkip skips gaps in the series.\nfunc (s *ExtendedStatsBucketAggregation) GapSkip() *ExtendedStatsBucketAggregation {\n\ts.gapPolicy = \"skip\"\n\treturn s\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (s *ExtendedStatsBucketAggregation) Meta(metaData map[string]interface{}) *ExtendedStatsBucketAggregation {\n\ts.meta = metaData\n\treturn s\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (s *ExtendedStatsBucketAggregation) BucketsPath(bucketsPaths ...string) *ExtendedStatsBucketAggregation {\n\ts.bucketsPaths = append(s.bucketsPaths, bucketsPaths...)\n\treturn s\n}\n\n// Sigma sets number of standard deviations above/below the mean to display\nfunc (s *ExtendedStatsBucketAggregation) Sigma(sigma float32) *ExtendedStatsBucketAggregation {\n\ts.sigma = &sigma\n\treturn s\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (s *ExtendedStatsBucketAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"extended_stats_bucket\"] = params\n\n\tif s.format != \"\" {\n\t\tparams[\"format\"] = s.format\n\t}\n\tif s.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = s.gapPolicy\n\t}\n\n\t// Add buckets paths\n\tswitch len(s.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = s.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = s.bucketsPaths\n\t}\n\n\t// Add sigma is not zero or less\n\tif s.sigma != nil && *s.sigma >= 0 {\n\t\tparams[\"sigma\"] = *s.sigma\n\t}\n\n\t// Add Meta data if available\n\tif len(s.meta) > 0 {\n\t\tsource[\"meta\"] = s.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_extended_stats_bucket_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestExtendedStatsBucketAggregationWithGapPolicy(t *testing.T) {\n\tagg := NewExtendedStatsBucketAggregation().BucketsPath(\"the_sum\").GapPolicy(\"skip\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"extended_stats_bucket\":{\"buckets_path\":\"the_sum\",\"gap_policy\":\"skip\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestExtendedStatsBucketAggregation(t *testing.T) {\n\n\tagg := NewExtendedStatsBucketAggregation().BucketsPath(\"another_test\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"extended_stats_bucket\":{\"buckets_path\":\"another_test\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestExtendedStatsBucketAggregationWithSigma(t *testing.T) {\n\tagg := NewExtendedStatsBucketAggregation().BucketsPath(\"sigma_test\")\n\n\tagg.Sigma(3)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"extended_stats_bucket\":{\"buckets_path\":\"sigma_test\",\"sigma\":3}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_max_bucket.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MaxBucketAggregation is a sibling pipeline aggregation which identifies\n// the bucket(s) with the maximum value of a specified metric in a sibling\n// aggregation and outputs both the value and the key(s) of the bucket(s).\n// The specified metric must be numeric and the sibling aggregation must\n// be a multi-bucket aggregation.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-max-bucket-aggregation.html\ntype MaxBucketAggregation struct {\n\tformat    string\n\tgapPolicy string\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewMaxBucketAggregation creates and initializes a new MaxBucketAggregation.\nfunc NewMaxBucketAggregation() *MaxBucketAggregation {\n\treturn &MaxBucketAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *MaxBucketAggregation) Format(format string) *MaxBucketAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *MaxBucketAggregation) GapPolicy(gapPolicy string) *MaxBucketAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *MaxBucketAggregation) GapInsertZeros() *MaxBucketAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *MaxBucketAggregation) GapSkip() *MaxBucketAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MaxBucketAggregation) Meta(metaData map[string]interface{}) *MaxBucketAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *MaxBucketAggregation) BucketsPath(bucketsPaths ...string) *MaxBucketAggregation {\n\ta.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *MaxBucketAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"max_bucket\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\n\t// Add buckets paths\n\tswitch len(a.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_max_bucket_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMaxBucketAggregation(t *testing.T) {\n\tagg := NewMaxBucketAggregation().BucketsPath(\"the_sum\").GapPolicy(\"skip\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"max_bucket\":{\"buckets_path\":\"the_sum\",\"gap_policy\":\"skip\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_min_bucket.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MinBucketAggregation is a sibling pipeline aggregation which identifies\n// the bucket(s) with the maximum value of a specified metric in a sibling\n// aggregation and outputs both the value and the key(s) of the bucket(s).\n// The specified metric must be numeric and the sibling aggregation must\n// be a multi-bucket aggregation.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-min-bucket-aggregation.html\ntype MinBucketAggregation struct {\n\tformat    string\n\tgapPolicy string\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewMinBucketAggregation creates and initializes a new MinBucketAggregation.\nfunc NewMinBucketAggregation() *MinBucketAggregation {\n\treturn &MinBucketAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *MinBucketAggregation) Format(format string) *MinBucketAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *MinBucketAggregation) GapPolicy(gapPolicy string) *MinBucketAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *MinBucketAggregation) GapInsertZeros() *MinBucketAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *MinBucketAggregation) GapSkip() *MinBucketAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MinBucketAggregation) Meta(metaData map[string]interface{}) *MinBucketAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *MinBucketAggregation) BucketsPath(bucketsPaths ...string) *MinBucketAggregation {\n\ta.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *MinBucketAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"min_bucket\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\n\t// Add buckets paths\n\tswitch len(a.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_min_bucket_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMinBucketAggregation(t *testing.T) {\n\tagg := NewMinBucketAggregation().BucketsPath(\"sales_per_month>sales\").GapPolicy(\"skip\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"min_bucket\":{\"buckets_path\":\"sales_per_month\\u003esales\",\"gap_policy\":\"skip\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_mov_avg.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MovAvgAggregation operates on a series of data. It will slide a window\n// across the data and emit the average value of that window.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movavg-aggregation.html\n//\n// Deprecated: The MovAvgAggregation has been deprecated in 6.4.0. Use the more generate MovFnAggregation instead.\ntype MovAvgAggregation struct {\n\tformat    string\n\tgapPolicy string\n\tmodel     MovAvgModel\n\twindow    *int\n\tpredict   *int\n\tminimize  *bool\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewMovAvgAggregation creates and initializes a new MovAvgAggregation.\n//\n// Deprecated: The MovAvgAggregation has been deprecated in 6.4.0. Use the more generate MovFnAggregation instead.\nfunc NewMovAvgAggregation() *MovAvgAggregation {\n\treturn &MovAvgAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *MovAvgAggregation) Format(format string) *MovAvgAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *MovAvgAggregation) GapPolicy(gapPolicy string) *MovAvgAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *MovAvgAggregation) GapInsertZeros() *MovAvgAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *MovAvgAggregation) GapSkip() *MovAvgAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Model is used to define what type of moving average you want to use\n// in the series.\nfunc (a *MovAvgAggregation) Model(model MovAvgModel) *MovAvgAggregation {\n\ta.model = model\n\treturn a\n}\n\n// Window sets the window size for the moving average. This window will\n// \"slide\" across the series, and the values inside that window will\n// be used to calculate the moving avg value.\nfunc (a *MovAvgAggregation) Window(window int) *MovAvgAggregation {\n\ta.window = &window\n\treturn a\n}\n\n// Predict sets the number of predictions that should be returned.\n// Each prediction will be spaced at the intervals in the histogram.\n// E.g. a predict of 2 will return two new buckets at the end of the\n// histogram with the predicted values.\nfunc (a *MovAvgAggregation) Predict(numPredictions int) *MovAvgAggregation {\n\ta.predict = &numPredictions\n\treturn a\n}\n\n// Minimize determines if the model should be fit to the data using a\n// cost minimizing algorithm.\nfunc (a *MovAvgAggregation) Minimize(minimize bool) *MovAvgAggregation {\n\ta.minimize = &minimize\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MovAvgAggregation) Meta(metaData map[string]interface{}) *MovAvgAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *MovAvgAggregation) BucketsPath(bucketsPaths ...string) *MovAvgAggregation {\n\ta.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *MovAvgAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"moving_avg\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\tif a.model != nil {\n\t\tparams[\"model\"] = a.model.Name()\n\t\tsettings := a.model.Settings()\n\t\tif len(settings) > 0 {\n\t\t\tparams[\"settings\"] = settings\n\t\t}\n\t}\n\tif a.window != nil {\n\t\tparams[\"window\"] = *a.window\n\t}\n\tif a.predict != nil {\n\t\tparams[\"predict\"] = *a.predict\n\t}\n\tif a.minimize != nil {\n\t\tparams[\"minimize\"] = *a.minimize\n\t}\n\n\t// Add buckets paths\n\tswitch len(a.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n\n// -- Models for moving averages --\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movavg-aggregation.html#_models\n\n// MovAvgModel specifies the model to use with the MovAvgAggregation.\ntype MovAvgModel interface {\n\tName() string\n\tSettings() map[string]interface{}\n}\n\n// -- EWMA --\n\n// EWMAMovAvgModel calculates an exponentially weighted moving average.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movavg-aggregation.html#_ewma_exponentially_weighted\ntype EWMAMovAvgModel struct {\n\talpha *float64\n}\n\n// NewEWMAMovAvgModel creates and initializes a new EWMAMovAvgModel.\nfunc NewEWMAMovAvgModel() *EWMAMovAvgModel {\n\treturn &EWMAMovAvgModel{}\n}\n\n// Alpha controls the smoothing of the data. Alpha = 1 retains no memory\n// of past values (e.g. a random walk), while alpha = 0 retains infinite\n// memory of past values (e.g. the series mean). Useful values are somewhere\n// in between. Defaults to 0.5.\nfunc (m *EWMAMovAvgModel) Alpha(alpha float64) *EWMAMovAvgModel {\n\tm.alpha = &alpha\n\treturn m\n}\n\n// Name of the model.\nfunc (m *EWMAMovAvgModel) Name() string {\n\treturn \"ewma\"\n}\n\n// Settings of the model.\nfunc (m *EWMAMovAvgModel) Settings() map[string]interface{} {\n\tsettings := make(map[string]interface{})\n\tif m.alpha != nil {\n\t\tsettings[\"alpha\"] = *m.alpha\n\t}\n\treturn settings\n}\n\n// -- Holt linear --\n\n// HoltLinearMovAvgModel calculates a doubly exponential weighted moving average.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movavg-aggregation.html#_holt_linear\ntype HoltLinearMovAvgModel struct {\n\talpha *float64\n\tbeta  *float64\n}\n\n// NewHoltLinearMovAvgModel creates and initializes a new HoltLinearMovAvgModel.\nfunc NewHoltLinearMovAvgModel() *HoltLinearMovAvgModel {\n\treturn &HoltLinearMovAvgModel{}\n}\n\n// Alpha controls the smoothing of the data. Alpha = 1 retains no memory\n// of past values (e.g. a random walk), while alpha = 0 retains infinite\n// memory of past values (e.g. the series mean). Useful values are somewhere\n// in between. Defaults to 0.5.\nfunc (m *HoltLinearMovAvgModel) Alpha(alpha float64) *HoltLinearMovAvgModel {\n\tm.alpha = &alpha\n\treturn m\n}\n\n// Beta is equivalent to Alpha but controls the smoothing of the trend\n// instead of the data.\nfunc (m *HoltLinearMovAvgModel) Beta(beta float64) *HoltLinearMovAvgModel {\n\tm.beta = &beta\n\treturn m\n}\n\n// Name of the model.\nfunc (m *HoltLinearMovAvgModel) Name() string {\n\treturn \"holt\"\n}\n\n// Settings of the model.\nfunc (m *HoltLinearMovAvgModel) Settings() map[string]interface{} {\n\tsettings := make(map[string]interface{})\n\tif m.alpha != nil {\n\t\tsettings[\"alpha\"] = *m.alpha\n\t}\n\tif m.beta != nil {\n\t\tsettings[\"beta\"] = *m.beta\n\t}\n\treturn settings\n}\n\n// -- Holt Winters --\n\n// HoltWintersMovAvgModel calculates a triple exponential weighted moving average.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movavg-aggregation.html#_holt_winters\ntype HoltWintersMovAvgModel struct {\n\talpha           *float64\n\tbeta            *float64\n\tgamma           *float64\n\tperiod          *int\n\tseasonalityType string\n\tpad             *bool\n}\n\n// NewHoltWintersMovAvgModel creates and initializes a new HoltWintersMovAvgModel.\nfunc NewHoltWintersMovAvgModel() *HoltWintersMovAvgModel {\n\treturn &HoltWintersMovAvgModel{}\n}\n\n// Alpha controls the smoothing of the data. Alpha = 1 retains no memory\n// of past values (e.g. a random walk), while alpha = 0 retains infinite\n// memory of past values (e.g. the series mean). Useful values are somewhere\n// in between. Defaults to 0.5.\nfunc (m *HoltWintersMovAvgModel) Alpha(alpha float64) *HoltWintersMovAvgModel {\n\tm.alpha = &alpha\n\treturn m\n}\n\n// Beta is equivalent to Alpha but controls the smoothing of the trend\n// instead of the data.\nfunc (m *HoltWintersMovAvgModel) Beta(beta float64) *HoltWintersMovAvgModel {\n\tm.beta = &beta\n\treturn m\n}\n\nfunc (m *HoltWintersMovAvgModel) Gamma(gamma float64) *HoltWintersMovAvgModel {\n\tm.gamma = &gamma\n\treturn m\n}\n\nfunc (m *HoltWintersMovAvgModel) Period(period int) *HoltWintersMovAvgModel {\n\tm.period = &period\n\treturn m\n}\n\nfunc (m *HoltWintersMovAvgModel) SeasonalityType(typ string) *HoltWintersMovAvgModel {\n\tm.seasonalityType = typ\n\treturn m\n}\n\nfunc (m *HoltWintersMovAvgModel) Pad(pad bool) *HoltWintersMovAvgModel {\n\tm.pad = &pad\n\treturn m\n}\n\n// Name of the model.\nfunc (m *HoltWintersMovAvgModel) Name() string {\n\treturn \"holt_winters\"\n}\n\n// Settings of the model.\nfunc (m *HoltWintersMovAvgModel) Settings() map[string]interface{} {\n\tsettings := make(map[string]interface{})\n\tif m.alpha != nil {\n\t\tsettings[\"alpha\"] = *m.alpha\n\t}\n\tif m.beta != nil {\n\t\tsettings[\"beta\"] = *m.beta\n\t}\n\tif m.gamma != nil {\n\t\tsettings[\"gamma\"] = *m.gamma\n\t}\n\tif m.period != nil {\n\t\tsettings[\"period\"] = *m.period\n\t}\n\tif m.pad != nil {\n\t\tsettings[\"pad\"] = *m.pad\n\t}\n\tif m.seasonalityType != \"\" {\n\t\tsettings[\"type\"] = m.seasonalityType\n\t}\n\treturn settings\n}\n\n// -- Linear --\n\n// LinearMovAvgModel calculates a linearly weighted moving average, such\n// that older values are linearly less important. \"Time\" is determined\n// by position in collection.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movavg-aggregation.html#_linear\ntype LinearMovAvgModel struct {\n}\n\n// NewLinearMovAvgModel creates and initializes a new LinearMovAvgModel.\nfunc NewLinearMovAvgModel() *LinearMovAvgModel {\n\treturn &LinearMovAvgModel{}\n}\n\n// Name of the model.\nfunc (m *LinearMovAvgModel) Name() string {\n\treturn \"linear\"\n}\n\n// Settings of the model.\nfunc (m *LinearMovAvgModel) Settings() map[string]interface{} {\n\treturn nil\n}\n\n// -- Simple --\n\n// SimpleMovAvgModel calculates a simple unweighted (arithmetic) moving average.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movavg-aggregation.html#_simple\ntype SimpleMovAvgModel struct {\n}\n\n// NewSimpleMovAvgModel creates and initializes a new SimpleMovAvgModel.\nfunc NewSimpleMovAvgModel() *SimpleMovAvgModel {\n\treturn &SimpleMovAvgModel{}\n}\n\n// Name of the model.\nfunc (m *SimpleMovAvgModel) Name() string {\n\treturn \"simple\"\n}\n\n// Settings of the model.\nfunc (m *SimpleMovAvgModel) Settings() map[string]interface{} {\n\treturn nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_mov_avg_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMovAvgAggregation(t *testing.T) {\n\tagg := NewMovAvgAggregation().BucketsPath(\"the_sum\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"moving_avg\":{\"buckets_path\":\"the_sum\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMovAvgAggregationWithSimpleModel(t *testing.T) {\n\tagg := NewMovAvgAggregation().BucketsPath(\"the_sum\").Window(30).Model(NewSimpleMovAvgModel())\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"moving_avg\":{\"buckets_path\":\"the_sum\",\"model\":\"simple\",\"window\":30}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMovAvgAggregationWithLinearModel(t *testing.T) {\n\tagg := NewMovAvgAggregation().BucketsPath(\"the_sum\").Window(30).Model(NewLinearMovAvgModel())\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"moving_avg\":{\"buckets_path\":\"the_sum\",\"model\":\"linear\",\"window\":30}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMovAvgAggregationWithEWMAModel(t *testing.T) {\n\tagg := NewMovAvgAggregation().BucketsPath(\"the_sum\").Window(30).Model(NewEWMAMovAvgModel().Alpha(0.5))\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"moving_avg\":{\"buckets_path\":\"the_sum\",\"model\":\"ewma\",\"settings\":{\"alpha\":0.5},\"window\":30}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMovAvgAggregationWithHoltLinearModel(t *testing.T) {\n\tagg := NewMovAvgAggregation().BucketsPath(\"the_sum\").Window(30).\n\t\tModel(NewHoltLinearMovAvgModel().Alpha(0.5).Beta(0.4))\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"moving_avg\":{\"buckets_path\":\"the_sum\",\"model\":\"holt\",\"settings\":{\"alpha\":0.5,\"beta\":0.4},\"window\":30}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMovAvgAggregationWithHoltWintersModel(t *testing.T) {\n\tagg := NewMovAvgAggregation().BucketsPath(\"the_sum\").Window(30).Predict(10).Minimize(true).\n\t\tModel(NewHoltWintersMovAvgModel().Alpha(0.5).Beta(0.4).Gamma(0.3).Period(7).Pad(true))\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"moving_avg\":{\"buckets_path\":\"the_sum\",\"minimize\":true,\"model\":\"holt_winters\",\"predict\":10,\"settings\":{\"alpha\":0.5,\"beta\":0.4,\"gamma\":0.3,\"pad\":true,\"period\":7},\"window\":30}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_mov_fn.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MovFnAggregation, given an ordered series of data, will slice a window across\n// the data and allow the user to specify a custom script that is executed for\n// each window of data.\n//\n// You must pass a script to process the values. There are a number of predefined\n// script functions you can use as described here:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movfn-aggregation.html#_pre_built_functions.\n//\n// Example:\n//   agg := elastic.NewMovFnAggregation(\n//     \"the_sum\", // bucket path\n//     elastic.NewScript(\"MovingFunctions.stdDev(values, MovingFunctions.unweightedAvg(values))\"),\n//     10,        // window size\n//   )\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-movfn-aggregation.html.\ntype MovFnAggregation struct {\n\tscript    *Script\n\tformat    string\n\tgapPolicy string\n\twindow    int\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewMovFnAggregation creates and initializes a new MovFnAggregation.\n//\n// Deprecated: The MovFnAggregation has been deprecated in 6.4.0. Use the more generate MovFnAggregation instead.\nfunc NewMovFnAggregation(bucketsPath string, script *Script, window int) *MovFnAggregation {\n\treturn &MovFnAggregation{\n\t\tbucketsPaths: []string{bucketsPath},\n\t\tscript:       script,\n\t\twindow:       window,\n\t}\n}\n\n// Script is the script to run.\nfunc (a *MovFnAggregation) Script(script *Script) *MovFnAggregation {\n\ta.script = script\n\treturn a\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *MovFnAggregation) Format(format string) *MovFnAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *MovFnAggregation) GapPolicy(gapPolicy string) *MovFnAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *MovFnAggregation) GapInsertZeros() *MovFnAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *MovFnAggregation) GapSkip() *MovFnAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Window sets the window size for this aggregation.\nfunc (a *MovFnAggregation) Window(window int) *MovFnAggregation {\n\ta.window = window\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *MovFnAggregation) Meta(metaData map[string]interface{}) *MovFnAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *MovFnAggregation) BucketsPath(bucketsPaths ...string) *MovFnAggregation {\n\ta.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *MovFnAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"moving_fn\"] = params\n\n\t// Add buckets paths\n\tswitch len(a.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths\n\t}\n\n\t// Script\n\tif a.script != nil {\n\t\tsrc, err := a.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tparams[\"script\"] = src\n\t}\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\tparams[\"window\"] = a.window\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_mov_fn_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMovFnAggregation(t *testing.T) {\n\tagg := NewMovFnAggregation(\n\t\t\"the_sum\",\n\t\tNewScript(\"MovingFunctions.min(values)\"),\n\t\t10,\n\t)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"moving_fn\":{\"buckets_path\":\"the_sum\",\"script\":{\"source\":\"MovingFunctions.min(values)\"},\"window\":10}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_percentiles_bucket.go",
    "content": "// Copyright 2012-2015 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// PercentilesBucketAggregation is a sibling pipeline aggregation which calculates\n// percentiles across all bucket of a specified metric in a sibling aggregation.\n// The specified metric must be numeric and the sibling aggregation must\n// be a multi-bucket aggregation.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-percentiles-bucket-aggregation.html\ntype PercentilesBucketAggregation struct {\n\tformat       string\n\tgapPolicy    string\n\tpercents     []float64\n\tbucketsPaths []string\n\n\tmeta map[string]interface{}\n}\n\n// NewPercentilesBucketAggregation creates and initializes a new PercentilesBucketAggregation.\nfunc NewPercentilesBucketAggregation() *PercentilesBucketAggregation {\n\treturn &PercentilesBucketAggregation{}\n}\n\n// Format to apply the output value of this aggregation.\nfunc (p *PercentilesBucketAggregation) Format(format string) *PercentilesBucketAggregation {\n\tp.format = format\n\treturn p\n}\n\n// Percents to calculate percentiles for in this aggregation.\nfunc (p *PercentilesBucketAggregation) Percents(percents ...float64) *PercentilesBucketAggregation {\n\tp.percents = percents\n\treturn p\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (p *PercentilesBucketAggregation) GapPolicy(gapPolicy string) *PercentilesBucketAggregation {\n\tp.gapPolicy = gapPolicy\n\treturn p\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (p *PercentilesBucketAggregation) GapInsertZeros() *PercentilesBucketAggregation {\n\tp.gapPolicy = \"insert_zeros\"\n\treturn p\n}\n\n// GapSkip skips gaps in the series.\nfunc (p *PercentilesBucketAggregation) GapSkip() *PercentilesBucketAggregation {\n\tp.gapPolicy = \"skip\"\n\treturn p\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (p *PercentilesBucketAggregation) Meta(metaData map[string]interface{}) *PercentilesBucketAggregation {\n\tp.meta = metaData\n\treturn p\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (p *PercentilesBucketAggregation) BucketsPath(bucketsPaths ...string) *PercentilesBucketAggregation {\n\tp.bucketsPaths = append(p.bucketsPaths, bucketsPaths...)\n\treturn p\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (p *PercentilesBucketAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"percentiles_bucket\"] = params\n\n\tif p.format != \"\" {\n\t\tparams[\"format\"] = p.format\n\t}\n\tif p.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = p.gapPolicy\n\t}\n\n\t// Add buckets paths\n\tswitch len(p.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = p.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = p.bucketsPaths\n\t}\n\n\t// Add percents\n\tif len(p.percents) > 0 {\n\t\tparams[\"percents\"] = p.percents\n\t}\n\n\t// Add Meta data if available\n\tif len(p.meta) > 0 {\n\t\tsource[\"meta\"] = p.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_percentiles_bucket_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestPercentilesBucketAggregation(t *testing.T) {\n\tagg := NewPercentilesBucketAggregation().BucketsPath(\"the_sum\").GapPolicy(\"skip\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentiles_bucket\":{\"buckets_path\":\"the_sum\",\"gap_policy\":\"skip\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercentilesBucketAggregationWithPercents(t *testing.T) {\n\tagg := NewPercentilesBucketAggregation().BucketsPath(\"the_sum\").Percents(0.1, 1.0, 5.0, 25, 50)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percentiles_bucket\":{\"buckets_path\":\"the_sum\",\"percents\":[0.1,1,5,25,50]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_serial_diff.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SerialDiffAggregation implements serial differencing.\n// Serial differencing is a technique where values in a time series are\n// subtracted from itself at different time lags or periods.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-serialdiff-aggregation.html\ntype SerialDiffAggregation struct {\n\tformat    string\n\tgapPolicy string\n\tlag       *int\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewSerialDiffAggregation creates and initializes a new SerialDiffAggregation.\nfunc NewSerialDiffAggregation() *SerialDiffAggregation {\n\treturn &SerialDiffAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *SerialDiffAggregation) Format(format string) *SerialDiffAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *SerialDiffAggregation) GapPolicy(gapPolicy string) *SerialDiffAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *SerialDiffAggregation) GapInsertZeros() *SerialDiffAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *SerialDiffAggregation) GapSkip() *SerialDiffAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Lag specifies the historical bucket to subtract from the current value.\n// E.g. a lag of 7 will subtract the current value from the value 7 buckets\n// ago. Lag must be a positive, non-zero integer.\nfunc (a *SerialDiffAggregation) Lag(lag int) *SerialDiffAggregation {\n\ta.lag = &lag\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *SerialDiffAggregation) Meta(metaData map[string]interface{}) *SerialDiffAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *SerialDiffAggregation) BucketsPath(bucketsPaths ...string) *SerialDiffAggregation {\n\ta.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *SerialDiffAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"serial_diff\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\tif a.lag != nil {\n\t\tparams[\"lag\"] = *a.lag\n\t}\n\n\t// Add buckets paths\n\tswitch len(a.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_serial_diff_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSerialDiffAggregation(t *testing.T) {\n\tagg := NewSerialDiffAggregation().BucketsPath(\"the_sum\").Lag(7)\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"serial_diff\":{\"buckets_path\":\"the_sum\",\"lag\":7}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_stats_bucket.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// StatsBucketAggregation is a sibling pipeline aggregation which calculates\n// a variety of stats across all bucket of a specified metric in a sibling aggregation.\n// The specified metric must be numeric and the sibling aggregation must\n// be a multi-bucket aggregation.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-stats-bucket-aggregation.html\ntype StatsBucketAggregation struct {\n\tformat    string\n\tgapPolicy string\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewStatsBucketAggregation creates and initializes a new StatsBucketAggregation.\nfunc NewStatsBucketAggregation() *StatsBucketAggregation {\n\treturn &StatsBucketAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (s *StatsBucketAggregation) Format(format string) *StatsBucketAggregation {\n\ts.format = format\n\treturn s\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (s *StatsBucketAggregation) GapPolicy(gapPolicy string) *StatsBucketAggregation {\n\ts.gapPolicy = gapPolicy\n\treturn s\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (s *StatsBucketAggregation) GapInsertZeros() *StatsBucketAggregation {\n\ts.gapPolicy = \"insert_zeros\"\n\treturn s\n}\n\n// GapSkip skips gaps in the series.\nfunc (s *StatsBucketAggregation) GapSkip() *StatsBucketAggregation {\n\ts.gapPolicy = \"skip\"\n\treturn s\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (s *StatsBucketAggregation) Meta(metaData map[string]interface{}) *StatsBucketAggregation {\n\ts.meta = metaData\n\treturn s\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (s *StatsBucketAggregation) BucketsPath(bucketsPaths ...string) *StatsBucketAggregation {\n\ts.bucketsPaths = append(s.bucketsPaths, bucketsPaths...)\n\treturn s\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (s *StatsBucketAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"stats_bucket\"] = params\n\n\tif s.format != \"\" {\n\t\tparams[\"format\"] = s.format\n\t}\n\tif s.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = s.gapPolicy\n\t}\n\n\t// Add buckets paths\n\tswitch len(s.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = s.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = s.bucketsPaths\n\t}\n\n\t// Add Meta data if available\n\tif len(s.meta) > 0 {\n\t\tsource[\"meta\"] = s.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_stats_bucket_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestStatsBucketAggregation(t *testing.T) {\n\tagg := NewStatsBucketAggregation().BucketsPath(\"the_sum\").GapPolicy(\"skip\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"stats_bucket\":{\"buckets_path\":\"the_sum\",\"gap_policy\":\"skip\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_sum_bucket.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SumBucketAggregation is a sibling pipeline aggregation which calculates\n// the sum across all buckets of a specified metric in a sibling aggregation.\n// The specified metric must be numeric and the sibling aggregation must\n// be a multi-bucket aggregation.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-pipeline-sum-bucket-aggregation.html\ntype SumBucketAggregation struct {\n\tformat    string\n\tgapPolicy string\n\n\tmeta         map[string]interface{}\n\tbucketsPaths []string\n}\n\n// NewSumBucketAggregation creates and initializes a new SumBucketAggregation.\nfunc NewSumBucketAggregation() *SumBucketAggregation {\n\treturn &SumBucketAggregation{\n\t\tbucketsPaths: make([]string, 0),\n\t}\n}\n\n// Format to use on the output of this aggregation.\nfunc (a *SumBucketAggregation) Format(format string) *SumBucketAggregation {\n\ta.format = format\n\treturn a\n}\n\n// GapPolicy defines what should be done when a gap in the series is discovered.\n// Valid values include \"insert_zeros\" or \"skip\". Default is \"insert_zeros\".\nfunc (a *SumBucketAggregation) GapPolicy(gapPolicy string) *SumBucketAggregation {\n\ta.gapPolicy = gapPolicy\n\treturn a\n}\n\n// GapInsertZeros inserts zeros for gaps in the series.\nfunc (a *SumBucketAggregation) GapInsertZeros() *SumBucketAggregation {\n\ta.gapPolicy = \"insert_zeros\"\n\treturn a\n}\n\n// GapSkip skips gaps in the series.\nfunc (a *SumBucketAggregation) GapSkip() *SumBucketAggregation {\n\ta.gapPolicy = \"skip\"\n\treturn a\n}\n\n// Meta sets the meta data to be included in the aggregation response.\nfunc (a *SumBucketAggregation) Meta(metaData map[string]interface{}) *SumBucketAggregation {\n\ta.meta = metaData\n\treturn a\n}\n\n// BucketsPath sets the paths to the buckets to use for this pipeline aggregator.\nfunc (a *SumBucketAggregation) BucketsPath(bucketsPaths ...string) *SumBucketAggregation {\n\ta.bucketsPaths = append(a.bucketsPaths, bucketsPaths...)\n\treturn a\n}\n\n// Source returns the a JSON-serializable interface.\nfunc (a *SumBucketAggregation) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"sum_bucket\"] = params\n\n\tif a.format != \"\" {\n\t\tparams[\"format\"] = a.format\n\t}\n\tif a.gapPolicy != \"\" {\n\t\tparams[\"gap_policy\"] = a.gapPolicy\n\t}\n\n\t// Add buckets paths\n\tswitch len(a.bucketsPaths) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths[0]\n\tdefault:\n\t\tparams[\"buckets_path\"] = a.bucketsPaths\n\t}\n\n\t// Add Meta data if available\n\tif len(a.meta) > 0 {\n\t\tsource[\"meta\"] = a.meta\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_aggs_pipeline_sum_bucket_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSumBucketAggregation(t *testing.T) {\n\tagg := NewSumBucketAggregation().BucketsPath(\"the_sum\")\n\tsrc, err := agg.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"sum_bucket\":{\"buckets_path\":\"the_sum\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_pipeline_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestAggsIntegrationAvgBucket(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"sales\", NewSumAggregation().Field(\"price\"))\n\tbuilder = builder.Aggregation(\"sales_per_month\", h)\n\tbuilder = builder.Aggregation(\"avg_monthly_sales\", NewAvgBucketAggregation().BucketsPath(\"sales_per_month>sales\"))\n\n\tres, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.AvgBucket(\"avg_monthly_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected avg_monthly_sales aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected avg_monthly_sales aggregation\")\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatal(\"expected avg_monthly_sales.value != nil\")\n\t}\n\tif got, want := *agg.Value, float64(939.2); got != want {\n\t\tt.Fatalf(\"expected avg_monthly_sales.value=%v; got: %v\", want, got)\n\t}\n}\n\nfunc TestAggsIntegrationDerivative(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"sales\", NewSumAggregation().Field(\"price\"))\n\th = h.SubAggregation(\"sales_deriv\", NewDerivativeAggregation().BucketsPath(\"sales\"))\n\tbuilder = builder.Aggregation(\"sales_per_month\", h)\n\n\tres, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.DateHistogram(\"sales_per_month\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif got, want := len(agg.Buckets), 6; got != want {\n\t\tt.Fatalf(\"expected %d buckets; got: %d\", want, got)\n\t}\n\n\tif got, want := agg.Buckets[0].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[1].DocCount, int64(0); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[2].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[3].DocCount, int64(3); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[4].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[5].DocCount, int64(2); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\n\td, found := agg.Buckets[0].Derivative(\"sales_deriv\")\n\tif found {\n\t\tt.Fatal(\"expected no sales_deriv aggregation\")\n\t}\n\tif d != nil {\n\t\tt.Fatal(\"expected no sales_deriv aggregation\")\n\t}\n\n\td, found = agg.Buckets[1].Derivative(\"sales_deriv\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d.Value != nil {\n\t\tt.Fatal(\"expected sales_deriv value == nil\")\n\t}\n\n\td, found = agg.Buckets[2].Derivative(\"sales_deriv\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d.Value != nil {\n\t\tt.Fatal(\"expected sales_deriv value == nil\")\n\t}\n\n\td, found = agg.Buckets[3].Derivative(\"sales_deriv\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected sales_deriv value != nil\")\n\t}\n\tif got, want := *d.Value, float64(2348.0); got != want {\n\t\tt.Fatalf(\"expected sales_deriv.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[4].Derivative(\"sales_deriv\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected sales_deriv value != nil\")\n\t}\n\tif got, want := *d.Value, float64(-1658.0); got != want {\n\t\tt.Fatalf(\"expected sales_deriv.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[5].Derivative(\"sales_deriv\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected sales_deriv aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected sales_deriv value != nil\")\n\t}\n\tif got, want := *d.Value, float64(-722.0); got != want {\n\t\tt.Fatalf(\"expected sales_deriv.value=%v; got: %v\", want, got)\n\t}\n}\n\nfunc TestAggsIntegrationMaxBucket(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"sales\", NewSumAggregation().Field(\"price\"))\n\tbuilder = builder.Aggregation(\"sales_per_month\", h)\n\tbuilder = builder.Aggregation(\"max_monthly_sales\", NewMaxBucketAggregation().BucketsPath(\"sales_per_month>sales\"))\n\n\tres, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.MaxBucket(\"max_monthly_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected max_monthly_sales aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected max_monthly_sales aggregation\")\n\t}\n\tif got, want := len(agg.Keys), 1; got != want {\n\t\tt.Fatalf(\"expected len(max_monthly_sales.keys)=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Keys[0], \"2015-04-01\"; got != want {\n\t\tt.Fatalf(\"expected max_monthly_sales.keys[0]=%v; got: %v\", want, got)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatal(\"expected max_monthly_sales.value != nil\")\n\t}\n\tif got, want := *agg.Value, float64(2448); got != want {\n\t\tt.Fatalf(\"expected max_monthly_sales.value=%v; got: %v\", want, got)\n\t}\n}\n\nfunc TestAggsIntegrationMinBucket(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"sales\", NewSumAggregation().Field(\"price\"))\n\tbuilder = builder.Aggregation(\"sales_per_month\", h)\n\tbuilder = builder.Aggregation(\"min_monthly_sales\", NewMinBucketAggregation().BucketsPath(\"sales_per_month>sales\"))\n\n\tres, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.MinBucket(\"min_monthly_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected min_monthly_sales aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected min_monthly_sales aggregation\")\n\t}\n\tif got, want := len(agg.Keys), 1; got != want {\n\t\tt.Fatalf(\"expected len(min_monthly_sales.keys)=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Keys[0], \"2015-06-01\"; got != want {\n\t\tt.Fatalf(\"expected min_monthly_sales.keys[0]=%v; got: %v\", want, got)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatal(\"expected min_monthly_sales.value != nil\")\n\t}\n\tif got, want := *agg.Value, float64(68); got != want {\n\t\tt.Fatalf(\"expected min_monthly_sales.value=%v; got: %v\", want, got)\n\t}\n}\n\nfunc TestAggsIntegrationSumBucket(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"sales\", NewSumAggregation().Field(\"price\"))\n\tbuilder = builder.Aggregation(\"sales_per_month\", h)\n\tbuilder = builder.Aggregation(\"sum_monthly_sales\", NewSumBucketAggregation().BucketsPath(\"sales_per_month>sales\"))\n\n\tres, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.SumBucket(\"sum_monthly_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected sum_monthly_sales aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected sum_monthly_sales aggregation\")\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatal(\"expected sum_monthly_sales.value != nil\")\n\t}\n\tif got, want := *agg.Value, float64(4696.0); got != want {\n\t\tt.Fatalf(\"expected sum_monthly_sales.value=%v; got: %v\", want, got)\n\t}\n}\n\nfunc TestAggsIntegrationMovAvg(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"the_sum\", NewSumAggregation().Field(\"price\"))\n\th = h.SubAggregation(\"the_movavg\", NewMovAvgAggregation().BucketsPath(\"the_sum\"))\n\tbuilder = builder.Aggregation(\"my_date_histo\", h)\n\n\tres, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.DateHistogram(\"my_date_histo\")\n\tif !found {\n\t\tt.Fatal(\"expected sum_monthly_sales aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected sum_monthly_sales aggregation\")\n\t}\n\tif got, want := len(agg.Buckets), 6; got != want {\n\t\tt.Fatalf(\"expected %d buckets; got: %d\", want, got)\n\t}\n\n\td, found := agg.Buckets[0].MovAvg(\"the_movavg\")\n\tif found {\n\t\tt.Fatal(\"expected no the_movavg aggregation\")\n\t}\n\tif d != nil {\n\t\tt.Fatal(\"expected no the_movavg aggregation\")\n\t}\n\n\td, found = agg.Buckets[1].MovAvg(\"the_movavg\")\n\tif found {\n\t\tt.Fatal(\"expected no the_movavg aggregation\")\n\t}\n\tif d != nil {\n\t\tt.Fatal(\"expected no the_movavg aggregation\")\n\t}\n\n\td, found = agg.Buckets[2].MovAvg(\"the_movavg\")\n\tif !found {\n\t\tt.Fatal(\"expected the_movavg aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected the_movavg aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected the_movavg value\")\n\t}\n\tif got, want := *d.Value, float64(1290.0); got != want {\n\t\tt.Fatalf(\"expected %v buckets; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[3].MovAvg(\"the_movavg\")\n\tif !found {\n\t\tt.Fatal(\"expected the_movavg aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected the_movavg aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected the_movavg value\")\n\t}\n\tif got, want := *d.Value, float64(695.0); got != want {\n\t\tt.Fatalf(\"expected %v buckets; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[4].MovAvg(\"the_movavg\")\n\tif !found {\n\t\tt.Fatal(\"expected the_movavg aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected the_movavg aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected the_movavg value\")\n\t}\n\tif got, want := *d.Value, float64(1279.3333333333333); got != want {\n\t\tt.Fatalf(\"expected %v buckets; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[5].MovAvg(\"the_movavg\")\n\tif !found {\n\t\tt.Fatal(\"expected the_movavg aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected the_movavg aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected the_movavg value\")\n\t}\n\tif got, want := *d.Value, float64(1157.0); got != want {\n\t\tt.Fatalf(\"expected %v buckets; got: %v\", want, got)\n\t}\n}\n\nfunc TestAggsIntegrationCumulativeSum(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"sales\", NewSumAggregation().Field(\"price\"))\n\th = h.SubAggregation(\"cumulative_sales\", NewCumulativeSumAggregation().BucketsPath(\"sales\"))\n\tbuilder = builder.Aggregation(\"sales_per_month\", h)\n\n\tres, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.DateHistogram(\"sales_per_month\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif got, want := len(agg.Buckets), 6; got != want {\n\t\tt.Fatalf(\"expected %d buckets; got: %d\", want, got)\n\t}\n\n\tif got, want := agg.Buckets[0].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[1].DocCount, int64(0); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[2].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[3].DocCount, int64(3); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[4].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[5].DocCount, int64(2); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\n\td, found := agg.Buckets[0].CumulativeSum(\"cumulative_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected cumulative_sales value != nil\")\n\t}\n\tif got, want := *d.Value, float64(1290.0); got != want {\n\t\tt.Fatalf(\"expected cumulative_sales.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[1].CumulativeSum(\"cumulative_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected cumulative_sales value != nil\")\n\t}\n\tif got, want := *d.Value, float64(1290.0); got != want {\n\t\tt.Fatalf(\"expected cumulative_sales.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[2].CumulativeSum(\"cumulative_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected cumulative_sales value != nil\")\n\t}\n\tif got, want := *d.Value, float64(1390.0); got != want {\n\t\tt.Fatalf(\"expected cumulative_sales.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[3].CumulativeSum(\"cumulative_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected cumulative_sales value != nil\")\n\t}\n\tif got, want := *d.Value, float64(3838.0); got != want {\n\t\tt.Fatalf(\"expected cumulative_sales.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[4].CumulativeSum(\"cumulative_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected cumulative_sales value != nil\")\n\t}\n\tif got, want := *d.Value, float64(4628.0); got != want {\n\t\tt.Fatalf(\"expected cumulative_sales.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[5].CumulativeSum(\"cumulative_sales\")\n\tif !found {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected cumulative_sales aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected cumulative_sales value != nil\")\n\t}\n\tif got, want := *d.Value, float64(4696.0); got != want {\n\t\tt.Fatalf(\"expected cumulative_sales.value=%v; got: %v\", want, got)\n\t}\n}\n\nfunc TestAggsIntegrationBucketScript(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"total_sales\", NewSumAggregation().Field(\"price\"))\n\tappleFilter := NewFilterAggregation().Filter(NewTermQuery(\"manufacturer\", \"Apple\"))\n\tappleFilter = appleFilter.SubAggregation(\"sales\", NewSumAggregation().Field(\"price\"))\n\th = h.SubAggregation(\"apple_sales\", appleFilter)\n\th = h.SubAggregation(\"apple_percentage\",\n\t\tNewBucketScriptAggregation().\n\t\t\tGapPolicy(\"insert_zeros\").\n\t\t\tAddBucketsPath(\"appleSales\", \"apple_sales>sales\").\n\t\t\tAddBucketsPath(\"totalSales\", \"total_sales\").\n\t\t\tScript(NewScript(\"params.appleSales / params.totalSales * 100\")))\n\tbuilder = builder.Aggregation(\"sales_per_month\", h)\n\n\tres, err := builder.Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"%v (maybe scripting is disabled?)\", err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.DateHistogram(\"sales_per_month\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif got, want := len(agg.Buckets), 6; got != want {\n\t\tt.Fatalf(\"expected %d buckets; got: %d\", want, got)\n\t}\n\n\tif got, want := agg.Buckets[0].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[1].DocCount, int64(0); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[2].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[3].DocCount, int64(3); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[4].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[5].DocCount, int64(2); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\n\td, found := agg.Buckets[0].BucketScript(\"apple_percentage\")\n\tif !found {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected apple_percentage value != nil\")\n\t}\n\tif got, want := *d.Value, float64(100.0); got != want {\n\t\tt.Fatalf(\"expected apple_percentage.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[1].BucketScript(\"apple_percentage\")\n\tif !found {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d.Value != nil {\n\t\tt.Fatal(\"expected apple_percentage value == nil\")\n\t}\n\n\td, found = agg.Buckets[2].BucketScript(\"apple_percentage\")\n\tif !found {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected apple_percentage value != nil\")\n\t}\n\tif got, want := *d.Value, float64(0.0); got != want {\n\t\tt.Fatalf(\"expected apple_percentage.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[3].BucketScript(\"apple_percentage\")\n\tif !found {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected apple_percentage value != nil\")\n\t}\n\tif got, want := *d.Value, float64(34.64052287581699); got != want {\n\t\tt.Fatalf(\"expected apple_percentage.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[4].BucketScript(\"apple_percentage\")\n\tif !found {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected apple_percentage value != nil\")\n\t}\n\tif got, want := *d.Value, float64(0.0); got != want {\n\t\tt.Fatalf(\"expected apple_percentage.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[5].BucketScript(\"apple_percentage\")\n\tif !found {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected apple_percentage aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected apple_percentage value != nil\")\n\t}\n\tif got, want := *d.Value, float64(0.0); got != want {\n\t\tt.Fatalf(\"expected apple_percentage.value=%v; got: %v\", want, got)\n\t}\n}\n\nfunc TestAggsIntegrationBucketSelector(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"total_sales\", NewSumAggregation().Field(\"price\"))\n\th = h.SubAggregation(\"sales_bucket_filter\",\n\t\tNewBucketSelectorAggregation().\n\t\t\tAddBucketsPath(\"totalSales\", \"total_sales\").\n\t\t\tScript(NewScript(\"params.totalSales <= 100\")))\n\tbuilder = builder.Aggregation(\"sales_per_month\", h)\n\n\tres, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"%v (maybe scripting is disabled?)\", err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.DateHistogram(\"sales_per_month\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif got, want := len(agg.Buckets), 2; got != want {\n\t\tt.Fatalf(\"expected %d buckets; got: %d\", want, got)\n\t}\n\n\tif got, want := agg.Buckets[0].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[1].DocCount, int64(2); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n}\n\nfunc TestAggsIntegrationSerialDiff(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tbuilder := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true)\n\th := NewDateHistogramAggregation().Field(\"time\").CalendarInterval(\"month\")\n\th = h.SubAggregation(\"sales\", NewSumAggregation().Field(\"price\"))\n\th = h.SubAggregation(\"the_diff\", NewSerialDiffAggregation().BucketsPath(\"sales\").Lag(1))\n\tbuilder = builder.Aggregation(\"sales_per_month\", h)\n\n\tres, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\n\taggs := res.Aggregations\n\tif aggs == nil {\n\t\tt.Fatal(\"expected aggregations != nil; got: nil\")\n\t}\n\n\tagg, found := aggs.DateHistogram(\"sales_per_month\")\n\tif !found {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif agg == nil {\n\t\tt.Fatal(\"expected sales_per_month aggregation\")\n\t}\n\tif got, want := len(agg.Buckets), 6; got != want {\n\t\tt.Fatalf(\"expected %d buckets; got: %d\", want, got)\n\t}\n\n\tif got, want := agg.Buckets[0].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[1].DocCount, int64(0); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[2].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[3].DocCount, int64(3); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[4].DocCount, int64(1); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\tif got, want := agg.Buckets[5].DocCount, int64(2); got != want {\n\t\tt.Fatalf(\"expected DocCount=%d; got: %d\", want, got)\n\t}\n\n\td, found := agg.Buckets[0].SerialDiff(\"the_diff\")\n\tif found {\n\t\tt.Fatal(\"expected no the_diff aggregation\")\n\t}\n\tif d != nil {\n\t\tt.Fatal(\"expected no the_diff aggregation\")\n\t}\n\n\td, found = agg.Buckets[1].SerialDiff(\"the_diff\")\n\tif found {\n\t\tt.Fatal(\"expected no the_diff aggregation\")\n\t}\n\tif d != nil {\n\t\tt.Fatal(\"expected no the_diff aggregation\")\n\t}\n\n\td, found = agg.Buckets[2].SerialDiff(\"the_diff\")\n\tif found {\n\t\tt.Fatal(\"expected no the_diff aggregation\")\n\t}\n\tif d != nil {\n\t\tt.Fatal(\"expected no the_diff aggregation\")\n\t}\n\n\td, found = agg.Buckets[3].SerialDiff(\"the_diff\")\n\tif !found {\n\t\tt.Fatal(\"expected the_diff aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected the_diff aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected the_diff value != nil\")\n\t}\n\tif got, want := *d.Value, float64(2348.0); got != want {\n\t\tt.Fatalf(\"expected the_diff.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[4].SerialDiff(\"the_diff\")\n\tif !found {\n\t\tt.Fatal(\"expected the_diff aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected the_diff aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected the_diff value != nil\")\n\t}\n\tif got, want := *d.Value, float64(-1658.0); got != want {\n\t\tt.Fatalf(\"expected the_diff.value=%v; got: %v\", want, got)\n\t}\n\n\td, found = agg.Buckets[5].SerialDiff(\"the_diff\")\n\tif !found {\n\t\tt.Fatal(\"expected the_diff aggregation\")\n\t}\n\tif d == nil {\n\t\tt.Fatal(\"expected the_diff aggregation\")\n\t}\n\tif d.Value == nil {\n\t\tt.Fatal(\"expected the_diff value != nil\")\n\t}\n\tif got, want := *d.Value, float64(-722.0); got != want {\n\t\tt.Fatalf(\"expected the_diff.value=%v; got: %v\", want, got)\n\t}\n}\n"
  },
  {
    "path": "search_aggs_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n)\n\n// TestAggs is an integration test for most aggregation types.\nfunc TestAggs(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\ttweet1 := tweet{\n\t\tUser:     \"olivere\",\n\t\tRetweets: 108,\n\t\tMessage:  \"Welcome to Golang and Elasticsearch.\",\n\t\tImage:    \"http://golang.org/doc/gopher/gophercolor.png\",\n\t\tTags:     []string{\"golang\", \"elasticsearch\"},\n\t\tLocation: \"48.1333,11.5667\", // lat,lon\n\t\tCreated:  time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser:     \"olivere\",\n\t\tRetweets: 0,\n\t\tMessage:  \"Another unrelated topic.\",\n\t\tTags:     []string{\"golang\"},\n\t\tLocation: \"48.1189,11.4289\", // lat,lon\n\t\tCreated:  time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser:     \"sandrae\",\n\t\tRetweets: 12,\n\t\tMessage:  \"Cycling is fun.\",\n\t\tTags:     []string{\"sports\", \"cycling\"},\n\t\tLocation: \"47.7167,11.7167\", // lat,lon\n\t\tCreated:  time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcount, err := client.Count(testIndexName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := int64(3), count; want != have {\n\t\tt.Fatalf(\"expected %d documents, got %d\", want, have)\n\t}\n\n\t// Match all should return all documents\n\tall := NewMatchAllQuery()\n\n\t// Terms Aggregate by user name\n\tglobalAgg := NewGlobalAggregation()\n\tusersAgg := NewTermsAggregation().Field(\"user\").Size(10).OrderByCountDesc()\n\tretweetsAgg := NewTermsAggregation().Field(\"retweets\").Size(10)\n\tmultiTermsAgg := NewMultiTermsAggregation().Terms(\"user\").MultiTerms(MultiTerm{Field: \"tags\", Missing: \"unclassified\"}).Size(10)\n\tavgRetweetsAgg := NewAvgAggregation().Field(\"retweets\")\n\tavgRetweetsWithMetaAgg := NewAvgAggregation().Field(\"retweetsMeta\").Meta(map[string]interface{}{\"meta\": true})\n\tweightedAvgRetweetsAgg := NewWeightedAvgAggregation().\n\t\tValue(&MultiValuesSourceFieldConfig{FieldName: \"retweets\"}).\n\t\tWeight(&MultiValuesSourceFieldConfig{FieldName: \"weight\", Missing: 1.0})\n\tminRetweetsAgg := NewMinAggregation().Field(\"retweets\")\n\tmaxRetweetsAgg := NewMaxAggregation().Field(\"retweets\")\n\tmedianAbsDevRetweetsAgg := NewMedianAbsoluteDeviationAggregation().Field(\"retweets\")\n\tsumRetweetsAgg := NewSumAggregation().Field(\"retweets\")\n\tstatsRetweetsAgg := NewStatsAggregation().Field(\"retweets\")\n\textstatsRetweetsAgg := NewExtendedStatsAggregation().Field(\"retweets\")\n\tvalueCountRetweetsAgg := NewValueCountAggregation().Field(\"retweets\")\n\tpercentilesRetweetsAgg := NewPercentilesAggregation().Field(\"retweets\")\n\tpercentileRanksRetweetsAgg := NewPercentileRanksAggregation().Field(\"retweets\").Values(25, 50, 75)\n\tcardinalityAgg := NewCardinalityAggregation().Field(\"user\")\n\tsignificantTermsAgg := NewSignificantTermsAggregation().Field(\"message\")\n\trareTermsAgg := NewRareTermsAggregation().Field(\"message\")\n\tsamplerAgg := NewSamplerAggregation().SubAggregation(\"tagged_with\", NewTermsAggregation().Field(\"tags\"))\n\tdiversifiedSamplerAgg := NewDiversifiedSamplerAggregation().Field(\"user\").SubAggregation(\"tagged_with\", NewSignificantTermsAggregation().Field(\"tags\"))\n\tretweetsRangeAgg := NewRangeAggregation().Field(\"retweets\").Lt(10).Between(10, 100).Gt(100)\n\tretweetsKeyedRangeAgg := NewRangeAggregation().Field(\"retweets\").Keyed(true).Lt(10).Between(10, 100).Gt(100)\n\tdateRangeAgg := NewDateRangeAggregation().Field(\"created\").Lt(\"2012-01-01\").Between(\"2012-01-01\", \"2013-01-01\").Gt(\"2013-01-01\")\n\tmissingTagsAgg := NewMissingAggregation().Field(\"tags\")\n\tretweetsHistoAgg := NewHistogramAggregation().Field(\"retweets\").Interval(100)\n\tautoDateHistoAgg := NewAutoDateHistogramAggregation().Field(\"created\").Buckets(2).Missing(\"1900-01-01\").Format(\"yyyy-MM-dd\")\n\tdateHistoAgg := NewDateHistogramAggregation().Field(\"created\").CalendarInterval(\"year\")\n\tdateHistoKeyedAgg := NewDateHistogramAggregation().Field(\"created\").CalendarInterval(\"year\").Keyed(true)\n\tretweetsFilterAgg := NewFilterAggregation().Filter(\n\t\tNewRangeQuery(\"created\").Gte(\"2012-01-01\").Lte(\"2012-12-31\")).\n\t\tSubAggregation(\"avgRetweetsSub\", NewAvgAggregation().Field(\"retweets\"))\n\tqueryFilterAgg := NewFilterAggregation().Filter(NewTermQuery(\"tags\", \"golang\"))\n\ttopTagsHitsAgg := NewTopHitsAggregation().Sort(\"created\", false).Size(5).FetchSource(true)\n\ttopTagsAgg := NewTermsAggregation().Field(\"tags\").Size(3).SubAggregation(\"top_tag_hits\", topTagsHitsAgg)\n\tgeoBoundsAgg := NewGeoBoundsAggregation().Field(\"location\")\n\tgeoHashAgg := NewGeoHashGridAggregation().Field(\"location\").Precision(5)\n\tgeoCentroidAgg := NewGeoCentroidAggregation().Field(\"location\")\n\tgeoTileAgg := NewGeoTileGridAggregation().Field(\"location\")\n\ttopMetricsAgg := NewTopMetricsAggregation().\n\t\tField(\"user\").\n\t\tField(\"retweets\").\n\t\tSort(\"retweets\", false).\n\t\tSize(2)\n\n\t// Run query\n\tbuilder := client.Search().Index(testIndexName).Query(all).Pretty(true)\n\tbuilder = builder.Aggregation(\"global\", globalAgg)\n\tbuilder = builder.Aggregation(\"users\", usersAgg)\n\tbuilder = builder.Aggregation(\"retweets\", retweetsAgg)\n\tbuilder = builder.Aggregation(\"multiterms\", multiTermsAgg)\n\tbuilder = builder.Aggregation(\"avgRetweets\", avgRetweetsAgg)\n\tbuilder = builder.Aggregation(\"avgRetweetsWithMeta\", avgRetweetsWithMetaAgg)\n\tbuilder = builder.Aggregation(\"weightedAvgRetweets\", weightedAvgRetweetsAgg)\n\tbuilder = builder.Aggregation(\"minRetweets\", minRetweetsAgg)\n\tbuilder = builder.Aggregation(\"maxRetweets\", maxRetweetsAgg)\n\tbuilder = builder.Aggregation(\"medianAbsDevRetweets\", medianAbsDevRetweetsAgg)\n\tbuilder = builder.Aggregation(\"sumRetweets\", sumRetweetsAgg)\n\tbuilder = builder.Aggregation(\"statsRetweets\", statsRetweetsAgg)\n\tbuilder = builder.Aggregation(\"extstatsRetweets\", extstatsRetweetsAgg)\n\tbuilder = builder.Aggregation(\"valueCountRetweets\", valueCountRetweetsAgg)\n\tbuilder = builder.Aggregation(\"percentilesRetweets\", percentilesRetweetsAgg)\n\tbuilder = builder.Aggregation(\"percentileRanksRetweets\", percentileRanksRetweetsAgg)\n\tbuilder = builder.Aggregation(\"usersCardinality\", cardinalityAgg)\n\tbuilder = builder.Aggregation(\"significantTerms\", significantTermsAgg)\n\tbuilder = builder.Aggregation(\"rareTerms\", rareTermsAgg)\n\tbuilder = builder.Aggregation(\"sample\", samplerAgg)\n\tbuilder = builder.Aggregation(\"diversified_sampler\", diversifiedSamplerAgg)\n\tbuilder = builder.Aggregation(\"retweetsRange\", retweetsRangeAgg)\n\tbuilder = builder.Aggregation(\"retweetsKeyedRange\", retweetsKeyedRangeAgg)\n\tbuilder = builder.Aggregation(\"dateRange\", dateRangeAgg)\n\tbuilder = builder.Aggregation(\"missingTags\", missingTagsAgg)\n\tbuilder = builder.Aggregation(\"retweetsHisto\", retweetsHistoAgg)\n\tbuilder = builder.Aggregation(\"autoDateHisto\", autoDateHistoAgg)\n\tbuilder = builder.Aggregation(\"dateHisto\", dateHistoAgg)\n\tbuilder = builder.Aggregation(\"dateHistoKeyed\", dateHistoKeyedAgg)\n\tbuilder = builder.Aggregation(\"retweetsFilter\", retweetsFilterAgg)\n\tbuilder = builder.Aggregation(\"queryFilter\", queryFilterAgg)\n\tbuilder = builder.Aggregation(\"top-tags\", topTagsAgg)\n\tbuilder = builder.Aggregation(\"viewport\", geoBoundsAgg)\n\tbuilder = builder.Aggregation(\"geohashed\", geoHashAgg)\n\tbuilder = builder.Aggregation(\"centroid\", geoCentroidAgg)\n\tbuilder = builder.Aggregation(\"geotile-grid\", geoTileAgg)\n\tbuilder = builder.Aggregation(\"top-metrics\", topMetricsAgg)\n\n\t// Unnamed filters\n\tcountByUserAgg := NewFiltersAggregation().\n\t\tFilters(NewTermQuery(\"user\", \"olivere\"), NewTermQuery(\"user\", \"sandrae\")).\n\t\tOtherBucket(true).OtherBucketKey(\"other\")\n\tbuilder = builder.Aggregation(\"countByUser\", countByUserAgg)\n\t// Named filters\n\tcountByUserAgg2 := NewFiltersAggregation().\n\t\tFilterWithName(\"olivere\", NewTermQuery(\"user\", \"olivere\")).\n\t\tFilterWithName(\"sandrae\", NewTermQuery(\"user\", \"sandrae\"))\n\tbuilder = builder.Aggregation(\"countByUser2\", countByUserAgg2)\n\t// AdjacencyMatrix\n\tadjacencyMatrixAgg := NewAdjacencyMatrixAggregation().\n\t\tFilters(\"groupA\", NewTermQuery(\"user\", \"olivere\")).\n\t\tFilters(\"groupB\", NewTermQuery(\"user\", \"sandrae\"))\n\tbuilder = builder.Aggregation(\"interactions\", adjacencyMatrixAgg)\n\t// AvgBucket\n\tdateHisto := NewDateHistogramAggregation().Field(\"created\").CalendarInterval(\"year\")\n\tdateHisto = dateHisto.SubAggregation(\"sumOfRetweets\", NewSumAggregation().Field(\"retweets\"))\n\tbuilder = builder.Aggregation(\"avgBucketDateHisto\", dateHisto)\n\tbuilder = builder.Aggregation(\"avgSumOfRetweets\", NewAvgBucketAggregation().BucketsPath(\"avgBucketDateHisto>sumOfRetweets\"))\n\t// MinBucket\n\tdateHisto = NewDateHistogramAggregation().Field(\"created\").CalendarInterval(\"year\")\n\tdateHisto = dateHisto.SubAggregation(\"sumOfRetweets\", NewSumAggregation().Field(\"retweets\"))\n\tbuilder = builder.Aggregation(\"minBucketDateHisto\", dateHisto)\n\tbuilder = builder.Aggregation(\"minBucketSumOfRetweets\", NewMinBucketAggregation().BucketsPath(\"minBucketDateHisto>sumOfRetweets\"))\n\t// MaxBucket\n\tdateHisto = NewDateHistogramAggregation().Field(\"created\").CalendarInterval(\"year\")\n\tdateHisto = dateHisto.SubAggregation(\"sumOfRetweets\", NewSumAggregation().Field(\"retweets\"))\n\tbuilder = builder.Aggregation(\"maxBucketDateHisto\", dateHisto)\n\tbuilder = builder.Aggregation(\"maxBucketSumOfRetweets\", NewMaxBucketAggregation().BucketsPath(\"maxBucketDateHisto>sumOfRetweets\"))\n\t// SumBucket\n\tdateHisto = NewDateHistogramAggregation().Field(\"created\").CalendarInterval(\"year\")\n\tdateHisto = dateHisto.SubAggregation(\"sumOfRetweets\", NewSumAggregation().Field(\"retweets\"))\n\tbuilder = builder.Aggregation(\"sumBucketDateHisto\", dateHisto)\n\tbuilder = builder.Aggregation(\"sumBucketSumOfRetweets\", NewSumBucketAggregation().BucketsPath(\"sumBucketDateHisto>sumOfRetweets\"))\n\t// MovAvg\n\tdateHisto = NewDateHistogramAggregation().Field(\"created\").CalendarInterval(\"year\")\n\tdateHisto = dateHisto.SubAggregation(\"sumOfRetweets\", NewSumAggregation().Field(\"retweets\"))\n\tdateHisto = dateHisto.SubAggregation(\"movingAvg\", NewMovAvgAggregation().BucketsPath(\"sumOfRetweets\"))\n\tdateHisto = dateHisto.SubAggregation(\"movingFn\", NewMovFnAggregation(\"sumOfRetweets\", NewScript(\"MovingFunctions.sum(values)\"), 10))\n\tbuilder = builder.Aggregation(\"movingAvgDateHisto\", dateHisto)\n\tsearchResult, err := builder.Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected TotalHits() = %d; got: %d\", 3, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 3 {\n\t\tt.Errorf(\"expected len(Hits.Hits) = %d; got: %d\", 3, len(searchResult.Hits.Hits))\n\t}\n\tagg := searchResult.Aggregations\n\tif agg == nil {\n\t\tt.Fatalf(\"expected Aggregations != nil; got: nil\")\n\t}\n\n\t// Search for non-existent aggregate should return (nil, false)\n\t{\n\t\tagg, found := agg.Terms(\"no-such-aggregate\")\n\t\tif found {\n\t\t\tt.Errorf(\"expected unknown aggregation to not be found; got: %v\", found)\n\t\t}\n\t\tif agg != nil {\n\t\t\tt.Errorf(\"expected unknown aggregation to return %v; got %v\", nil, agg)\n\t\t}\n\t}\n\n\t// Global\n\t{\n\t\tagg, found := agg.Global(\"global\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.DocCount != 3 {\n\t\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 3, agg.DocCount)\n\t\t}\n\t}\n\n\t// Search for existent aggregate (by name) should return (aggregate, true)\n\t{\n\t\tagg, found := agg.Terms(\"users\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 2 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 2, len(agg.Buckets))\n\t\t}\n\t\tif agg.Buckets[0].Key != \"olivere\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"olivere\", agg.Buckets[0].Key)\n\t\t}\n\t\tif agg.Buckets[0].DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t\t}\n\t\tif agg.Buckets[1].Key != \"sandrae\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"sandrae\", agg.Buckets[1].Key)\n\t\t}\n\t\tif agg.Buckets[1].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t\t}\n\t}\n\n\t// A terms aggregate with keys that are not strings\n\t{\n\t\tagg, found := agg.Terms(\"retweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 3 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 3, len(agg.Buckets))\n\t\t}\n\n\t\tif agg.Buckets[0].Key != float64(0) {\n\t\t\tt.Errorf(\"expected %v; got: %v\", float64(0), agg.Buckets[0].Key)\n\t\t}\n\t\tif got, err := agg.Buckets[0].KeyNumber.Int64(); err != nil {\n\t\t\tt.Errorf(\"expected %d; got: %v\", 0, agg.Buckets[0].Key)\n\t\t} else if got != 0 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 0, got)\n\t\t}\n\t\tif agg.Buckets[0].KeyNumber != \"0\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"0\", agg.Buckets[0].KeyNumber)\n\t\t}\n\t\tif agg.Buckets[0].KeyNumber.String() != \"0\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"0\", agg.Buckets[0].KeyNumber.String())\n\t\t}\n\t\tif agg.Buckets[0].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[0].DocCount)\n\t\t}\n\n\t\tif agg.Buckets[1].Key != float64(12) {\n\t\t\tt.Errorf(\"expected %v; got: %v\", float64(12), agg.Buckets[1].Key)\n\t\t}\n\t\tif got, err := agg.Buckets[1].KeyNumber.Int64(); err != nil {\n\t\t\tt.Errorf(\"expected %d; got: %v\", 0, agg.Buckets[1].KeyNumber)\n\t\t} else if got != 12 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 12, got)\n\t\t}\n\t\tif agg.Buckets[1].KeyNumber != \"12\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"12\", agg.Buckets[1].KeyNumber)\n\t\t}\n\t\tif agg.Buckets[1].KeyNumber.String() != \"12\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"12\", agg.Buckets[1].KeyNumber.String())\n\t\t}\n\t\tif agg.Buckets[1].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t\t}\n\n\t\tif agg.Buckets[2].Key != float64(108) {\n\t\t\tt.Errorf(\"expected %v; got: %v\", float64(108), agg.Buckets[2].Key)\n\t\t}\n\t\tif got, err := agg.Buckets[2].KeyNumber.Int64(); err != nil {\n\t\t\tt.Errorf(\"expected %d; got: %v\", 108, agg.Buckets[2].KeyNumber)\n\t\t} else if got != 108 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 108, got)\n\t\t}\n\t\tif agg.Buckets[2].KeyNumber != \"108\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"108\", agg.Buckets[2].KeyNumber)\n\t\t}\n\t\tif agg.Buckets[2].KeyNumber.String() != \"108\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"108\", agg.Buckets[2].KeyNumber.String())\n\t\t}\n\t\tif agg.Buckets[2].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[2].DocCount)\n\t\t}\n\t}\n\n\t// A multi terms aggregate\n\t{\n\t\tagg, found := agg.MultiTerms(\"multiterms\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 4 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 4, len(agg.Buckets))\n\t\t}\n\t\tif want, have := 2, len(agg.Buckets[0].Key); want != have {\n\t\t\tt.Errorf(\"expected %v; got: %v\", want, have)\n\t\t}\n\t\tif want, have := \"olivere\", agg.Buckets[0].Key[0]; want != have {\n\t\t\tt.Errorf(\"expected %v; got: %v\", want, have)\n\t\t}\n\t\tif want, have := \"golang\", agg.Buckets[0].Key[1]; want != have {\n\t\t\tt.Errorf(\"expected %v; got: %v\", want, have)\n\t\t}\n\t\tif agg.Buckets[0].KeyAsString == nil {\n\t\t\tt.Fatal(\"expected string not nil\")\n\t\t}\n\t\tif want, have := \"olivere|golang\", *agg.Buckets[0].KeyAsString; want != have {\n\t\t\tt.Errorf(\"expected %v; got: %v\", want, have)\n\t\t}\n\t\tif agg.Buckets[0].DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t\t}\n\t}\n\n\t// avgRetweets\n\t{\n\t\tagg, found := agg.Avg(\"avgRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Value == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Value)\n\t\t}\n\t\tif *agg.Value != 40.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 40.0, *agg.Value)\n\t\t}\n\t}\n\n\t// avgRetweetsWithMeta\n\t{\n\t\tagg, found := agg.Avg(\"avgRetweetsWithMeta\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Meta == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", agg.Meta)\n\t\t}\n\t\tmetaDataValue, found := agg.Meta[\"meta\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected to return meta data key %q; got: %v\", \"meta\", found)\n\t\t}\n\t\tif flag, ok := metaDataValue.(bool); !ok {\n\t\t\tt.Fatalf(\"expected to return meta data key type %T; got: %T\", true, metaDataValue)\n\t\t} else if flag != true {\n\t\t\tt.Fatalf(\"expected to return meta data key value %v; got: %v\", true, flag)\n\t\t}\n\t}\n\n\t// weightedAvgRetweets\n\t{\n\t\tagg, found := agg.Avg(\"weightedAvgRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Value == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Value)\n\t\t}\n\t\tif *agg.Value != 40.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 40.0, *agg.Value)\n\t\t}\n\t}\n\n\t// minRetweets\n\t{\n\t\tagg, found := agg.Min(\"minRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Value == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Value)\n\t\t}\n\t\tif *agg.Value != 0.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 0.0, *agg.Value)\n\t\t}\n\t}\n\n\t// maxRetweets\n\t{\n\t\tagg, found := agg.Max(\"maxRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Value == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Value)\n\t\t}\n\t\tif *agg.Value != 108.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 108.0, *agg.Value)\n\t\t}\n\t}\n\n\t// medianAbsDevRetweets\n\t{\n\t\tagg, found := agg.MedianAbsoluteDeviation(\"medianAbsDevRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Value == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Value)\n\t\t}\n\t\tif *agg.Value != 12.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 12.0, *agg.Value)\n\t\t}\n\t}\n\n\t// sumRetweets\n\t{\n\t\tagg, found := agg.Sum(\"sumRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Value == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Value)\n\t\t}\n\t\tif *agg.Value != 120.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 120.0, *agg.Value)\n\t\t}\n\t}\n\n\t// statsRetweets\n\t{\n\t\tagg, found := agg.Stats(\"statsRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Count != 3 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 3, agg.Count)\n\t\t}\n\t\tif agg.Min == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Min)\n\t\t}\n\t\tif *agg.Min != 0.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 0.0, *agg.Min)\n\t\t}\n\t\tif agg.Max == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Max)\n\t\t}\n\t\tif *agg.Max != 108.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 108.0, *agg.Max)\n\t\t}\n\t\tif agg.Avg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Avg)\n\t\t}\n\t\tif *agg.Avg != 40.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 40.0, *agg.Avg)\n\t\t}\n\t\tif agg.Sum == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Sum)\n\t\t}\n\t\tif *agg.Sum != 120.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 120.0, *agg.Sum)\n\t\t}\n\t}\n\n\t// extstatsRetweets\n\t{\n\t\tagg, found := agg.ExtendedStats(\"extstatsRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Count != 3 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 3, agg.Count)\n\t\t}\n\t\tif agg.Min == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Min)\n\t\t}\n\t\tif *agg.Min != 0.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 0.0, *agg.Min)\n\t\t}\n\t\tif agg.Max == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Max)\n\t\t}\n\t\tif *agg.Max != 108.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 108.0, *agg.Max)\n\t\t}\n\t\tif agg.Avg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Avg)\n\t\t}\n\t\tif *agg.Avg != 40.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 40.0, *agg.Avg)\n\t\t}\n\t\tif agg.Sum == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Sum)\n\t\t}\n\t\tif *agg.Sum != 120.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 120.0, *agg.Sum)\n\t\t}\n\t\tif agg.SumOfSquares == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.SumOfSquares)\n\t\t}\n\t\tif *agg.SumOfSquares != 11808.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 11808.0, *agg.SumOfSquares)\n\t\t}\n\t\tif agg.Variance == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Variance)\n\t\t}\n\t\tif *agg.Variance != 2336.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 2336.0, *agg.Variance)\n\t\t}\n\t\tif agg.StdDeviation == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.StdDeviation)\n\t\t}\n\t\tif *agg.StdDeviation != 48.33218389437829 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 48.33218389437829, *agg.StdDeviation)\n\t\t}\n\t}\n\n\t// valueCountRetweets\n\t{\n\t\tagg, found := agg.ValueCount(\"valueCountRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Value == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Value)\n\t\t}\n\t\tif *agg.Value != 3.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 3.0, *agg.Value)\n\t\t}\n\t}\n\n\t// percentilesRetweets\n\t{\n\t\tagg, found := agg.Percentiles(\"percentilesRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\t// ES 1.4.x returns  7: {\"1.0\":...}\n\t\t// ES 1.5.0 returns 14: {\"1.0\":..., \"1.0_as_string\":...}\n\t\t// So we're relaxing the test here.\n\t\tif len(agg.Values) == 0 {\n\t\t\tt.Errorf(\"expected at least %d value; got: %d\\nValues are: %#v\", 1, len(agg.Values), agg.Values)\n\t\t}\n\t\tif _, found := agg.Values[\"0.0\"]; found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", false, found)\n\t\t}\n\t\tif agg.Values[\"1.0\"] != 0.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 0.0, agg.Values[\"1.0\"])\n\t\t}\n\t\tif agg.Values[\"5.0\"] != 0.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 0.0, agg.Values[\"1.0\"])\n\t\t}\n\t\tif agg.Values[\"25.0\"] != 3.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 3.0, agg.Values[\"25.0\"])\n\t\t}\n\t\tif agg.Values[\"50.0\"] != 12.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 12.0, agg.Values[\"50.0\"])\n\t\t}\n\t\tif agg.Values[\"75.0\"] != 84.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 84.0, agg.Values[\"75.0\"])\n\t\t}\n\t\tif agg.Values[\"95.0\"] != 108.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 108.0, agg.Values[\"95.0\"])\n\t\t}\n\t\tif agg.Values[\"99.0\"] != 108.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 108.0, agg.Values[\"99.0\"])\n\t\t}\n\t}\n\n\t// percentileRanksRetweets\n\t{\n\t\tagg, found := agg.PercentileRanks(\"percentileRanksRetweets\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Values) == 0 {\n\t\t\tt.Errorf(\"expected at least %d value; got %d\\nValues are: %#v\", 1, len(agg.Values), agg.Values)\n\t\t}\n\t\tif _, found := agg.Values[\"0.0\"]; found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg.Values[\"25.0\"] != 45.06172839506173 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 45.06172839506173, agg.Values[\"25.0\"])\n\t\t}\n\t\tif agg.Values[\"50.0\"] != 60.49382716049383 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 60.49382716049383, agg.Values[\"50.0\"])\n\t\t}\n\t\tif agg.Values[\"75.0\"] != 100.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 100.0, agg.Values[\"75.0\"])\n\t\t}\n\t}\n\n\t// usersCardinality\n\t{\n\t\tagg, found := agg.Cardinality(\"usersCardinality\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Value == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", *agg.Value)\n\t\t}\n\t\tif *agg.Value != 2 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 2, *agg.Value)\n\t\t}\n\t}\n\n\t// retweetsFilter\n\t{\n\t\tagg, found := agg.Filter(\"retweetsFilter\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.DocCount != 2 {\n\t\t\tt.Fatalf(\"expected %v; got: %v\", 2, agg.DocCount)\n\t\t}\n\t\t// Retrieve sub-aggregation\n\t\tsub, found := agg.Avg(\"avgRetweetsSub\")\n\t\tif !found {\n\t\t\tt.Error(\"expected sub-aggregation \\\"avgRetweets\\\" to be found; got false\")\n\t\t}\n\t\tif sub == nil {\n\t\t\tt.Fatal(\"expected sub-aggregation \\\"avgRetweets\\\"; got nil\")\n\t\t}\n\t\tif sub.Value == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", sub.Value)\n\t\t}\n\t\tif *sub.Value != 54.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 54.0, *sub.Value)\n\t\t}\n\t}\n\n\t// queryFilter\n\t{\n\t\tagg, found := agg.Filter(\"queryFilter\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.DocCount != 2 {\n\t\t\tt.Fatalf(\"expected %v; got: %v\", 2, agg.DocCount)\n\t\t}\n\t}\n\n\t// significantTerms\n\t{\n\t\tagg, found := agg.SignificantTerms(\"significantTerms\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.DocCount != 3 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 3, agg.DocCount)\n\t\t}\n\t\tif len(agg.Buckets) != 0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 0, len(agg.Buckets))\n\t\t}\n\t}\n\n\t// rareTerms\n\t{\n\t\tagg, found := agg.SignificantTerms(\"rareTerms\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.DocCount != 0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 0, agg.DocCount)\n\t\t}\n\t\tif len(agg.Buckets) != 11 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 11, len(agg.Buckets))\n\t\t}\n\t}\n\n\t// sampler\n\t{\n\t\tagg, found := agg.Sampler(\"sample\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.DocCount != 3 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 3, agg.DocCount)\n\t\t}\n\t\tsub, found := agg.Aggregations[\"tagged_with\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected sub aggregation %q\", \"tagged_with\")\n\t\t}\n\t\tif sub == nil {\n\t\t\tt.Fatalf(\"expected sub aggregation %q; got: %v\", \"tagged_with\", sub)\n\t\t}\n\t}\n\n\t// diversified_sampler\n\t{\n\t\tagg, found := agg.DiversifiedSampler(\"diversified_sampler\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.DocCount != 2 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 2, agg.DocCount)\n\t\t}\n\t}\n\n\t// retweetsRange\n\t{\n\t\tagg, found := agg.Range(\"retweetsRange\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 3 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 3, len(agg.Buckets))\n\t\t}\n\t\tif agg.Buckets[0].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[0].DocCount)\n\t\t}\n\t\tif agg.Buckets[1].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t\t}\n\t\tif agg.Buckets[2].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[2].DocCount)\n\t\t}\n\t}\n\n\t// retweetsKeyedRange\n\t{\n\t\tagg, found := agg.KeyedRange(\"retweetsKeyedRange\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 3 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 3, len(agg.Buckets))\n\t\t}\n\t\t_, found = agg.Buckets[\"no-such-key\"]\n\t\tif found {\n\t\t\tt.Fatalf(\"expected bucket to not be found; got: %v\", found)\n\t\t}\n\t\tbucket, found := agg.Buckets[\"*-10.0\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected bucket to be found; got: %v\", found)\n\t\t}\n\t\tif bucket.DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, bucket.DocCount)\n\t\t}\n\t\tbucket, found = agg.Buckets[\"10.0-100.0\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected bucket to be found; got: %v\", found)\n\t\t}\n\t\tif bucket.DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, bucket.DocCount)\n\t\t}\n\t\tbucket, found = agg.Buckets[\"100.0-*\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected bucket to be found; got: %v\", found)\n\t\t}\n\t\tif bucket.DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, bucket.DocCount)\n\t\t}\n\t}\n\n\t// dateRange\n\t{\n\t\tagg, found := agg.DateRange(\"dateRange\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.Buckets[0].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[0].DocCount)\n\t\t}\n\t\tif agg.Buckets[0].From != nil {\n\t\t\tt.Fatal(\"expected From to be nil\")\n\t\t}\n\t\tif agg.Buckets[0].To == nil {\n\t\t\tt.Fatal(\"expected To to be != nil\")\n\t\t}\n\t\tif *agg.Buckets[0].To != 1.325376e+12 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 1.325376e+12, *agg.Buckets[0].To)\n\t\t}\n\t\tif agg.Buckets[0].ToAsString != \"2012-01-01T00:00:00.000Z\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"2012-01-01T00:00:00.000Z\", agg.Buckets[0].ToAsString)\n\t\t}\n\t\tif agg.Buckets[1].DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, agg.Buckets[1].DocCount)\n\t\t}\n\t\tif agg.Buckets[1].From == nil {\n\t\t\tt.Fatal(\"expected From to be != nil\")\n\t\t}\n\t\tif *agg.Buckets[1].From != 1.325376e+12 {\n\t\t\tt.Errorf(\"expected From = %v; got: %v\", 1.325376e+12, *agg.Buckets[1].From)\n\t\t}\n\t\tif agg.Buckets[1].FromAsString != \"2012-01-01T00:00:00.000Z\" {\n\t\t\tt.Errorf(\"expected FromAsString = %q; got: %q\", \"2012-01-01T00:00:00.000Z\", agg.Buckets[1].FromAsString)\n\t\t}\n\t\tif agg.Buckets[1].To == nil {\n\t\t\tt.Fatal(\"expected To to be != nil\")\n\t\t}\n\t\tif *agg.Buckets[1].To != 1.3569984e+12 {\n\t\t\tt.Errorf(\"expected To = %v; got: %v\", 1.3569984e+12, *agg.Buckets[1].To)\n\t\t}\n\t\tif agg.Buckets[1].ToAsString != \"2013-01-01T00:00:00.000Z\" {\n\t\t\tt.Errorf(\"expected ToAsString = %q; got: %q\", \"2013-01-01T00:00:00.000Z\", agg.Buckets[1].ToAsString)\n\t\t}\n\t\tif agg.Buckets[2].DocCount != 0 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 0, agg.Buckets[2].DocCount)\n\t\t}\n\t\tif agg.Buckets[2].To != nil {\n\t\t\tt.Fatal(\"expected To to be nil\")\n\t\t}\n\t\tif agg.Buckets[2].From == nil {\n\t\t\tt.Fatal(\"expected From to be != nil\")\n\t\t}\n\t\tif *agg.Buckets[2].From != 1.3569984e+12 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 1.3569984e+12, *agg.Buckets[2].From)\n\t\t}\n\t\tif agg.Buckets[2].FromAsString != \"2013-01-01T00:00:00.000Z\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"2013-01-01T00:00:00.000Z\", agg.Buckets[2].FromAsString)\n\t\t}\n\t}\n\n\t// missingTags\n\t{\n\t\tagg, found := agg.Missing(\"missingTags\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif agg.DocCount != 0 {\n\t\t\tt.Errorf(\"expected searchResult.Aggregations[\\\"missingTags\\\"].DocCount = %v; got %v\", 0, agg.DocCount)\n\t\t}\n\t}\n\n\t// retweetsHisto\n\t{\n\t\tagg, found := agg.Histogram(\"retweetsHisto\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 2 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 2, len(agg.Buckets))\n\t\t}\n\t\tif agg.Buckets[0].DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t\t}\n\t\tif agg.Buckets[0].Key != 0.0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 0.0, agg.Buckets[0].Key)\n\t\t}\n\t\tif agg.Buckets[1].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t\t}\n\t\tif agg.Buckets[1].Key != 100.0 {\n\t\t\tt.Errorf(\"expected %v; got: %+v\", 100.0, agg.Buckets[1].Key)\n\t\t}\n\t}\n\n\t// autoDateHisto\n\t{\n\t\tagg, found := agg.DateHistogram(\"autoDateHisto\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 2 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 2, len(agg.Buckets))\n\t\t}\n\t}\n\n\t// dateHisto\n\t{\n\t\tagg, found := agg.DateHistogram(\"dateHisto\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 2 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 2, len(agg.Buckets))\n\t\t}\n\t\tif agg.Buckets[0].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[0].DocCount)\n\t\t}\n\t\tif agg.Buckets[0].Key != 1.29384e+12 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 1.29384e+12, agg.Buckets[0].Key)\n\t\t}\n\t\tif agg.Buckets[0].KeyAsString == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", agg.Buckets[0].KeyAsString)\n\t\t}\n\t\tif *agg.Buckets[0].KeyAsString != \"2011-01-01T00:00:00.000Z\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"2011-01-01T00:00:00.000Z\", *agg.Buckets[0].KeyAsString)\n\t\t}\n\t\tif agg.Buckets[1].DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, agg.Buckets[1].DocCount)\n\t\t}\n\t\tif agg.Buckets[1].Key != 1.325376e+12 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 1.325376e+12, agg.Buckets[1].Key)\n\t\t}\n\t\tif agg.Buckets[1].KeyAsString == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", agg.Buckets[1].KeyAsString)\n\t\t}\n\t\tif *agg.Buckets[1].KeyAsString != \"2012-01-01T00:00:00.000Z\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"2012-01-01T00:00:00.000Z\", *agg.Buckets[1].KeyAsString)\n\t\t}\n\t}\n\n\t// dateHistoKeyed\n\t{\n\t\tres, found := agg.KeyedDateHistogram(\"dateHistoKeyed\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif res == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(res.Buckets) != 2 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 2, len(res.Buckets))\n\t\t}\n\n\t\tbucket, ok := res.Buckets[\"2011-01-01T00:00:00.000Z\"]\n\t\tif !ok || bucket == nil {\n\t\t\tt.Fatalf(\"expected to have bucket with key %q\", \"2011-01-01T00:00:00.000Z\")\n\t\t}\n\t\tif bucket.DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, bucket.DocCount)\n\t\t}\n\t\tif bucket.Key != 1.29384e+12 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 1.29384e+12, bucket.Key)\n\t\t}\n\t\tif bucket.KeyAsString == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", bucket.KeyAsString)\n\t\t}\n\t\tif *bucket.KeyAsString != \"2011-01-01T00:00:00.000Z\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"2011-01-01T00:00:00.000Z\", *bucket.KeyAsString)\n\t\t}\n\n\t\tbucket, ok = res.Buckets[\"2012-01-01T00:00:00.000Z\"]\n\t\tif !ok || bucket == nil {\n\t\t\tt.Fatalf(\"expected to have bucket with key %q\", \"2012-01-01T00:00:00.000Z\")\n\t\t}\n\t\tif bucket.DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, bucket.DocCount)\n\t\t}\n\t\tif bucket.Key != 1.325376e+12 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 1.325376e+12, bucket.Key)\n\t\t}\n\t\tif bucket.KeyAsString == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: %v\", bucket.KeyAsString)\n\t\t}\n\t\tif *bucket.KeyAsString != \"2012-01-01T00:00:00.000Z\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"2012-01-01T00:00:00.000Z\", *bucket.KeyAsString)\n\t\t}\n\t}\n\n\t// topHits\n\t{\n\t\ttopTags, found := agg.Terms(\"top-tags\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif topTags == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif topTags.DocCountErrorUpperBound != 0 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 0, topTags.DocCountErrorUpperBound)\n\t\t}\n\t\tif topTags.SumOfOtherDocCount != 1 {\n\t\t\tt.Errorf(\"expected %v; got: %v\", 1, topTags.SumOfOtherDocCount)\n\t\t}\n\t\tif len(topTags.Buckets) != 3 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 3, len(topTags.Buckets))\n\t\t}\n\t\tif topTags.Buckets[0].DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, topTags.Buckets[0].DocCount)\n\t\t}\n\t\tif topTags.Buckets[0].Key != \"golang\" {\n\t\t\tt.Errorf(\"expected %v; got: %v\", \"golang\", topTags.Buckets[0].Key)\n\t\t}\n\t\ttopHits, found := topTags.Buckets[0].TopHits(\"top_tag_hits\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif topHits == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif topHits.Hits == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif topHits.Hits.TotalHits == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif topHits.Hits.TotalHits.Value != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, topHits.Hits.TotalHits.Value)\n\t\t}\n\t\tif topHits.Hits.Hits == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(topHits.Hits.Hits) != 2 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 2, len(topHits.Hits.Hits))\n\t\t}\n\t\thit := topHits.Hits.Hits[0]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif hit == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tvar tw tweet\n\t\tif err := json.Unmarshal(hit.Source, &tw); err != nil {\n\t\t\tt.Fatalf(\"expected no error; got: %v\", err)\n\t\t}\n\t\tif tw.Message != \"Welcome to Golang and Elasticsearch.\" {\n\t\t\tt.Errorf(\"expected %q; got: %q\", \"Welcome to Golang and Elasticsearch.\", tw.Message)\n\t\t}\n\t\tif topTags.Buckets[1].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, topTags.Buckets[1].DocCount)\n\t\t}\n\t\tif topTags.Buckets[1].Key != \"cycling\" {\n\t\t\tt.Errorf(\"expected %v; got: %v\", \"cycling\", topTags.Buckets[1].Key)\n\t\t}\n\t\ttopHits, found = topTags.Buckets[1].TopHits(\"top_tag_hits\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif topHits == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif topHits.Hits == nil {\n\t\t\tt.Fatal(\"expected != nil; got nil\")\n\t\t}\n\t\tif topHits.Hits.TotalHits == nil {\n\t\t\tt.Fatal(\"expected != nil; got nil\")\n\t\t}\n\t\tif topHits.Hits.TotalHits.Value != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, topHits.Hits.TotalHits.Value)\n\t\t}\n\t\tif topTags.Buckets[2].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, topTags.Buckets[2].DocCount)\n\t\t}\n\t\tif topTags.Buckets[2].Key != \"elasticsearch\" {\n\t\t\tt.Errorf(\"expected %v; got: %v\", \"elasticsearch\", topTags.Buckets[2].Key)\n\t\t}\n\t\ttopHits, found = topTags.Buckets[2].TopHits(\"top_tag_hits\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif topHits == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif topHits.Hits == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif topHits.Hits.TotalHits == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif topHits.Hits.TotalHits.Value != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, topHits.Hits.TotalHits.Value)\n\t\t}\n\t}\n\n\t// viewport via geo_bounds (1.3.0 has an error in that it doesn't output the aggregation name)\n\t{\n\t\tagg, found := agg.GeoBounds(\"viewport\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t}\n\n\t// geohashed via geohash\n\t{\n\t\tagg, found := agg.GeoHash(\"geohashed\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t}\n\n\t// geo_centroid\n\t{\n\t\tagg, found := agg.GeoCentroid(\"centroid\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t}\n\n\t// geotile grid\n\t{\n\t\tagg, found := agg.GeoTile(\"geotile-grid\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t}\n\n\t// Filters agg \"countByUser\" (unnamed)\n\t{\n\t\tagg, found := agg.Filters(\"countByUser\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 3 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 3, len(agg.Buckets))\n\t\t}\n\t\tif len(agg.NamedBuckets) != 0 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 0, len(agg.NamedBuckets))\n\t\t}\n\t\tif agg.Buckets[0].DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t\t}\n\t\tif agg.Buckets[1].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t\t}\n\t\tif agg.Buckets[2].DocCount != 0 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 0, agg.Buckets[2].DocCount)\n\t\t}\n\t}\n\n\t// Filters agg \"countByUser2\" (named)\n\t{\n\t\tagg, found := agg.Filters(\"countByUser2\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 0 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 0, len(agg.Buckets))\n\t\t}\n\t\tif len(agg.NamedBuckets) != 2 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 2, len(agg.NamedBuckets))\n\t\t}\n\t\tb, found := agg.NamedBuckets[\"olivere\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected bucket %q; got: %v\", \"olivere\", found)\n\t\t}\n\t\tif b == nil {\n\t\t\tt.Fatalf(\"expected bucket %q; got: %v\", \"olivere\", b)\n\t\t}\n\t\tif b.DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, b.DocCount)\n\t\t}\n\t\tb, found = agg.NamedBuckets[\"sandrae\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected bucket %q; got: %v\", \"sandrae\", found)\n\t\t}\n\t\tif b == nil {\n\t\t\tt.Fatalf(\"expected bucket %q; got: %v\", \"sandrae\", b)\n\t\t}\n\t\tif b.DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, b.DocCount)\n\t\t}\n\t}\n\n\t// AdjacencyMatrix agg \"adjacencyMatrixAgg\" (named)\n\t{\n\t\tagg, found := agg.AdjacencyMatrix(\"interactions\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif len(agg.Buckets) != 2 {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", 2, len(agg.Buckets))\n\t\t}\n\t\tif agg.Buckets[0].DocCount != 2 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t\t}\n\t\tif agg.Buckets[1].DocCount != 1 {\n\t\t\tt.Errorf(\"expected %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t\t}\n\t}\n\n\t// movingAvgDateHisto\n\t{\n\t\tagg, found := agg.DateHistogram(\"movingAvgDateHisto\")\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected %v; got: %v\", true, false)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\t\tif want, have := 2, len(agg.Buckets); want != have {\n\t\t\tt.Fatalf(\"expected %d buckets, have %d\", want, have)\n\t\t}\n\t\t// movingAvgDateHisto.Buckets[0]\n\t\tif want, have := int64(1), agg.Buckets[0].DocCount; want != have {\n\t\t\tt.Fatalf(\"expected %d docs in bucket 0, have %d\", want, have)\n\t\t}\n\t\tif want, have := 1293840000000.0, agg.Buckets[0].Key; want != have {\n\t\t\tt.Fatalf(\"expected key of %v in bucket 0, have %v\", want, have)\n\t\t}\n\t\tif have := agg.Buckets[0].KeyAsString; have == nil {\n\t\t\tt.Fatalf(\"expected key_as_string != nil in bucket 0, have %v\", have)\n\t\t}\n\t\tif want, have := \"2011-01-01T00:00:00.000Z\", *agg.Buckets[0].KeyAsString; want != have {\n\t\t\tt.Fatalf(\"expected key_as_string of %q in bucket 0, have %q\", want, have)\n\t\t}\n\t\tsumOfRetweetsAgg, found := agg.Buckets[0].SumBucket(\"sumOfRetweets\")\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected sub-aggregation %q\", \"sumOfRetweets\")\n\t\t}\n\t\tif have := sumOfRetweetsAgg.Value; have == nil {\n\t\t\tt.Fatalf(\"expected sumOfRetweets != nil, have %v\", have)\n\t\t}\n\t\tif want, have := 12.0, *sumOfRetweetsAgg.Value; want != have {\n\t\t\tt.Fatalf(\"expected sumOfRetweets = %v, have %v\", want, have)\n\t\t}\n\t\tmovingAvgAgg, found := agg.Buckets[0].MovAvg(\"movingAvg\")\n\t\tif found {\n\t\t\tt.Fatalf(\"expected no sub-aggregation %q\", \"movingAvg\")\n\t\t}\n\t\tif movingAvgAgg != nil {\n\t\t\tt.Fatalf(\"expected no sub-aggregation %q\", \"movingAvg\")\n\t\t}\n\t\tmovingFnAgg, found := agg.Buckets[0].MovFn(\"movingFn\")\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected sub-aggregation %q\", \"movingFn\")\n\t\t}\n\t\tif have := movingFnAgg.Value; have == nil {\n\t\t\tt.Fatalf(\"expected movingFn != nil, have %v\", have)\n\t\t}\n\t\tif want, have := 0.0, *movingFnAgg.Value; want != have {\n\t\t\tt.Fatalf(\"expected movingFn = %v, have %v\", want, have)\n\t\t}\n\t\t// movingAvgDateHisto.Buckets[1]\n\t\tif want, have := int64(2), agg.Buckets[1].DocCount; want != have {\n\t\t\tt.Fatalf(\"expected %d docs in bucket 1, have %d\", want, have)\n\t\t}\n\t\tif want, have := 1325376000000.0, agg.Buckets[1].Key; want != have {\n\t\t\tt.Fatalf(\"expected key of %v in bucket 1, have %v\", want, have)\n\t\t}\n\t\tif have := agg.Buckets[1].KeyAsString; have == nil {\n\t\t\tt.Fatalf(\"expected key_as_string != nil in bucket 1, have %v\", have)\n\t\t}\n\t\tif want, have := \"2012-01-01T00:00:00.000Z\", *agg.Buckets[1].KeyAsString; want != have {\n\t\t\tt.Fatalf(\"expected key_as_string of %q in bucket 1, have %q\", want, have)\n\t\t}\n\t\tsumOfRetweetsAgg, found = agg.Buckets[1].SumBucket(\"sumOfRetweets\")\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected sub-aggregation %q\", \"sumOfRetweets\")\n\t\t}\n\t\tif have := sumOfRetweetsAgg.Value; have == nil {\n\t\t\tt.Fatalf(\"expected sumOfRetweets != nil, have %v\", have)\n\t\t}\n\t\tif want, have := 108.0, *sumOfRetweetsAgg.Value; want != have {\n\t\t\tt.Fatalf(\"expected sumOfRetweets = %v, have %v\", want, have)\n\t\t}\n\t\tmovingAvgAgg, found = agg.Buckets[1].MovAvg(\"movingAvg\")\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected sub-aggregation %q\", \"movingAvg\")\n\t\t}\n\t\tif have := movingAvgAgg.Value; have == nil {\n\t\t\tt.Fatalf(\"expected movingAgg != nil, have %v\", have)\n\t\t}\n\t\tif want, have := 12.0, *movingAvgAgg.Value; want != have {\n\t\t\tt.Fatalf(\"expected movingAvg = %v, have %v\", want, have)\n\t\t}\n\t\tmovingFnAgg, found = agg.Buckets[1].MovFn(\"movingFn\")\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected sub-aggregation %q\", \"movingFn\")\n\t\t}\n\t\tif have := movingFnAgg.Value; have == nil {\n\t\t\tt.Fatalf(\"expected movingFn != nil, have %v\", have)\n\t\t}\n\t\tif want, have := 12.0, *movingFnAgg.Value; want != have {\n\t\t\tt.Fatalf(\"expected movingFn = %v, have %v\", want, have)\n\t\t}\n\t}\n\n\t// top metrics aggregation\n\t{\n\t\tagg, found := agg.TopMetrics(\"top-metrics\")\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected %v; got: %v\", true, false)\n\t\t}\n\t\tif agg == nil {\n\t\t\tt.Fatal(\"expected != nil; got: nil\")\n\t\t}\n\n\t\tif want, have := 2, len(agg.Top); want != have {\n\t\t\tt.Fatalf(\"expected %d top results, have %d\", want, have)\n\t\t}\n\n\t\tif want, have := \"olivere\", agg.Top[0].Metrics[\"user\"]; want != have {\n\t\t\tt.Fatalf(\"expected %v top user, have %v\", want, have)\n\t\t}\n\t\tif want, have := float64(108), agg.Top[0].Metrics[\"retweets\"]; want != have {\n\t\t\tt.Fatalf(\"expected %v top user, have %v\", want, have)\n\t\t}\n\t\tif want, have := float64(108), agg.Top[0].Sort[0]; want != have {\n\t\t\tt.Fatalf(\"expected %v sort value, have %v\", want, have)\n\t\t}\n\n\t\tif want, have := \"sandrae\", agg.Top[1].Metrics[\"user\"]; want != have {\n\t\t\tt.Fatalf(\"expected %v top user, have %v\", want, have)\n\t\t}\n\t\tif want, have := float64(12), agg.Top[1].Metrics[\"retweets\"]; want != have {\n\t\t\tt.Fatalf(\"expected %v top user, have %v\", want, have)\n\t\t}\n\t\tif want, have := float64(12), agg.Top[1].Sort[0]; want != have {\n\t\t\tt.Fatalf(\"expected %v sort value, have %v\", want, have)\n\t\t}\n\t}\n}\n\n// TestAggsCompositeIntegration is an integration test for the Composite aggregation.\nfunc TestAggsCompositeIntegration(t *testing.T) {\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser:     \"olivere\",\n\t\tRetweets: 108,\n\t\tMessage:  \"Welcome to Golang and Elasticsearch.\",\n\t\tImage:    \"http://golang.org/doc/gopher/gophercolor.png\",\n\t\tTags:     []string{\"golang\", \"elasticsearch\"},\n\t\tLocation: \"48.1333,11.5667\", // lat,lon\n\t\tCreated:  time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser:     \"olivere\",\n\t\tRetweets: 0,\n\t\tMessage:  \"Another unrelated topic.\",\n\t\tTags:     []string{\"golang\"},\n\t\tLocation: \"48.1189,11.4289\", // lat,lon\n\t\tCreated:  time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser:     \"sandrae\",\n\t\tRetweets: 12,\n\t\tMessage:  \"Cycling is fun.\",\n\t\tTags:     []string{\"sports\", \"cycling\"},\n\t\tLocation: \"47.7167,11.7167\", // lat,lon\n\t\tCreated:  time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tcount, err := client.Count(testIndexName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := int64(3), count; want != have {\n\t\tt.Fatalf(\"expected %d documents, got %d\", want, have)\n\t}\n\n\t// Match all should return all documents\n\tall := NewMatchAllQuery()\n\n\t// Terms Aggregate by user name\n\tbuilder := client.Search().Index(testIndexName).Query(all).Pretty(true)\n\tcomposite := NewCompositeAggregation().Sources(\n\t\tNewCompositeAggregationTermsValuesSource(\"composite_users\").Field(\"user\"),\n\t\tNewCompositeAggregationHistogramValuesSource(\"composite_retweets\", 1).MissingBucket(true).Field(\"retweets\"),\n\t\tNewCompositeAggregationDateHistogramValuesSource(\"composite_created\").CalendarInterval(\"1m\").Field(\"created\"),\n\t).Size(2)\n\tbuilder = builder.Aggregation(\"composite\", composite)\n\n\t// Run the query\n\tsearchResult, err := builder.Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\tif searchResult.Hits.TotalHits == nil {\n\t\tt.Errorf(\"expected Hits.TotalHits != nil; got: nil\")\n\t}\n\tif searchResult.Hits.TotalHits.Value != 3 {\n\t\tt.Errorf(\"expected Hits.TotalHits.Value = %d; got: %d\", 3, searchResult.Hits.TotalHits.Value)\n\t}\n\tif len(searchResult.Hits.Hits) != 3 {\n\t\tt.Errorf(\"expected len(Hits.Hits) = %d; got: %d\", 3, len(searchResult.Hits.Hits))\n\t}\n\tagg := searchResult.Aggregations\n\tif agg == nil {\n\t\tt.Fatalf(\"expected Aggregations != nil; got: nil\")\n\t}\n\n\t// Check outcome of 1st call (without \"after_key\" settings)\n\tvar afterKey map[string]interface{}\n\t{\n\t\tcompositeAggRes, found := agg.Composite(\"composite\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif compositeAggRes == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif want, have := 2, len(compositeAggRes.Buckets); want != have {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", want, have)\n\t\t}\n\t\tafterKey = compositeAggRes.AfterKey\n\t\tif len(afterKey) == 0 {\n\t\t\tt.Fatalf(\"expected after_key; got: %v\", afterKey)\n\t\t}\n\t\tif v, found := afterKey[\"composite_users\"]; !found {\n\t\t\tt.Fatalf(\"expected after_key.composite_users; got: %v\", afterKey)\n\t\t} else if want, have := \"olivere\", v; want != have {\n\t\t\tt.Fatalf(\"expected after_key.composite_users = %q; got: %q\", want, have)\n\t\t}\n\t\tif v, found := afterKey[\"composite_retweets\"]; !found {\n\t\t\tt.Fatalf(\"expected after_key.composite_retweets; got: %v\", afterKey)\n\t\t} else if want, have := 108.0, v; want != have {\n\t\t\tt.Fatalf(\"expected after_key.composite_retweets = %v; got: %v\", want, have)\n\t\t}\n\t\tif v, found := afterKey[\"composite_created\"]; !found {\n\t\t\tt.Fatalf(\"expected after_key.composite_created; got: %v\", afterKey)\n\t\t} else if want, have := 1355333880000.0, v; want != have {\n\t\t\tt.Fatalf(\"expected after_key.composite_created = %v; got: %v\", want, have)\n\t\t}\n\t}\n\n\t// Now paginate to the 2nd call via \"after_key\"\n\tbuilder = client.Search().Index(testIndexName).Query(all).Pretty(true)\n\tcomposite = NewCompositeAggregation().Sources(\n\t\tNewCompositeAggregationTermsValuesSource(\"composite_users\").Field(\"user\"),\n\t\tNewCompositeAggregationHistogramValuesSource(\"composite_retweets\", 1).Field(\"retweets\"),\n\t\tNewCompositeAggregationDateHistogramValuesSource(\"composite_created\").CalendarInterval(\"1m\").Field(\"created\"),\n\t).Size(2).AggregateAfter(afterKey)\n\tbuilder = builder.Aggregation(\"composite\", composite)\n\tsearchResult, err = builder.Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\tagg = searchResult.Aggregations\n\tif agg == nil {\n\t\tt.Fatalf(\"expected Aggregations != nil; got: nil\")\n\t}\n\n\t// Check outcome of 2nd call (with \"after_key\" settings)\n\t{\n\t\tcompositeAggRes, found := agg.Composite(\"composite\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif compositeAggRes == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif want, have := 1, len(compositeAggRes.Buckets); want != have {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", want, have)\n\t\t}\n\t\tafterKey = compositeAggRes.AfterKey\n\t\tif len(afterKey) == 0 {\n\t\t\tt.Fatalf(\"expected after_key; got: %v\", afterKey)\n\t\t}\n\t\tif v, found := afterKey[\"composite_users\"]; !found {\n\t\t\tt.Fatalf(\"expected after_key.composite_users; got: %v\", afterKey)\n\t\t} else if want, have := \"sandrae\", v; want != have {\n\t\t\tt.Fatalf(\"expected after_key.composite_users = %q; got: %q\", want, have)\n\t\t}\n\t\tif v, found := afterKey[\"composite_retweets\"]; !found {\n\t\t\tt.Fatalf(\"expected after_key.composite_retweets; got: %v\", afterKey)\n\t\t} else if want, have := 12.0, v; want != have {\n\t\t\tt.Fatalf(\"expected after_key.composite_retweets = %v; got: %v\", want, have)\n\t\t}\n\t\tif v, found := afterKey[\"composite_created\"]; !found {\n\t\t\tt.Fatalf(\"expected after_key.composite_created; got: %v\", afterKey)\n\t\t} else if want, have := 1321009080000.0, v; want != have {\n\t\t\tt.Fatalf(\"expected after_key.composite_created = %v; got: %v\", want, have)\n\t\t}\n\t}\n\n\t// Now paginate to the 3rd call via \"after_key\"\n\tbuilder = client.Search().Index(testIndexName).Query(all).Pretty(true)\n\tcomposite = NewCompositeAggregation().Sources(\n\t\tNewCompositeAggregationTermsValuesSource(\"composite_users\").Field(\"user\"),\n\t\tNewCompositeAggregationHistogramValuesSource(\"composite_retweets\", 1).Field(\"retweets\"),\n\t\tNewCompositeAggregationDateHistogramValuesSource(\"composite_created\").CalendarInterval(\"1m\").Field(\"created\"),\n\t).Size(2).AggregateAfter(afterKey)\n\tbuilder = builder.Aggregation(\"composite\", composite)\n\tsearchResult, err = builder.Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got: nil\")\n\t}\n\tagg = searchResult.Aggregations\n\tif agg == nil {\n\t\tt.Fatalf(\"expected Aggregations != nil; got: nil\")\n\t}\n\n\t// Check outcome of 3rd call (with \"after_key\" settings)\n\t{\n\t\tcompositeAggRes, found := agg.Composite(\"composite\")\n\t\tif !found {\n\t\t\tt.Errorf(\"expected %v; got: %v\", true, found)\n\t\t}\n\t\tif compositeAggRes == nil {\n\t\t\tt.Fatalf(\"expected != nil; got: nil\")\n\t\t}\n\t\tif want, have := 0, len(compositeAggRes.Buckets); want != have {\n\t\t\tt.Fatalf(\"expected %d; got: %d\", want, have)\n\t\t}\n\t\tafterKey = compositeAggRes.AfterKey\n\t\tif afterKey != nil {\n\t\t\tt.Fatalf(\"expected no after_key; got: %v\", afterKey)\n\t\t}\n\t}\n}\n\n// TestAggsMarshal ensures that marshaling aggregations back into a string\n// does not yield base64 encoded data. See https://github.com/olivere/elastic/issues/51\n// and https://groups.google.com/forum/#!topic/Golang-Nuts/38ShOlhxAYY for details.\nfunc TestAggsMarshal(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser:     \"olivere\",\n\t\tRetweets: 108,\n\t\tMessage:  \"Welcome to Golang and Elasticsearch.\",\n\t\tImage:    \"http://golang.org/doc/gopher/gophercolor.png\",\n\t\tTags:     []string{\"golang\", \"elasticsearch\"},\n\t\tLocation: \"48.1333,11.5667\", // lat,lon\n\t\tCreated:  time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\tall := NewMatchAllQuery()\n\tdhagg := NewDateHistogramAggregation().Field(\"created\").CalendarInterval(\"year\")\n\n\t// Run query\n\tbuilder := client.Search().Index(testIndexName).Query(all)\n\tbuilder = builder.Aggregation(\"dhagg\", dhagg)\n\tsearchResult, err := builder.Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.TotalHits() != 1 {\n\t\tt.Errorf(\"expected Hits.TotalHits = %d; got: %d\", 1, searchResult.TotalHits())\n\t}\n\tif _, found := searchResult.Aggregations[\"dhagg\"]; !found {\n\t\tt.Fatalf(\"expected aggregation %q\", \"dhagg\")\n\t}\n\tbuf, err := json.Marshal(searchResult)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\ts := string(buf)\n\tif i := strings.Index(s, `{\"dhagg\":{\"buckets\":[{\"key_as_string\":\"2012-01-01`); i < 0 {\n\t\tt.Errorf(\"expected to serialize aggregation into string; got: %v\", s)\n\t}\n}\n\nfunc TestAggsMetricsMin(t *testing.T) {\n\ts := `{\n\t\"min_price\": {\n  \t\"value\": 10\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Min(\"min_price\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(10) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(10), *agg.Value)\n\t}\n}\n\nfunc TestAggsMetricsMax(t *testing.T) {\n\ts := `{\n\t\"max_price\": {\n  \t\"value\": 35\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Max(\"max_price\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(35) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(35), *agg.Value)\n\t}\n}\n\nfunc TestAggsMetricsSum(t *testing.T) {\n\ts := `{\n\t\"intraday_return\": {\n  \t\"value\": 2.18\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Sum(\"intraday_return\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(2.18) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(2.18), *agg.Value)\n\t}\n}\n\nfunc TestAggsMetricsAvg(t *testing.T) {\n\ts := `{\n\t\"avg_grade\": {\n  \t\"value\": 75\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Avg(\"avg_grade\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(75) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(75), *agg.Value)\n\t}\n}\n\nfunc TestAggsMetricsValueCount(t *testing.T) {\n\ts := `{\n\t\"grades_count\": {\n  \t\"value\": 10\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.ValueCount(\"grades_count\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(10) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(10), *agg.Value)\n\t}\n}\n\nfunc TestAggsMetricsCardinality(t *testing.T) {\n\ts := `{\n\t\"author_count\": {\n  \t\"value\": 12\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Cardinality(\"author_count\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(12) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(12), *agg.Value)\n\t}\n}\n\nfunc TestAggsMetricsStats(t *testing.T) {\n\ts := `{\n\t\"grades_stats\": {\n    \"count\": 6,\n    \"min\": 60,\n    \"max\": 98,\n    \"avg\": 78.5,\n    \"sum\": 471\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Stats(\"grades_stats\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Count != int64(6) {\n\t\tt.Fatalf(\"expected aggregation Count = %v; got: %v\", int64(6), agg.Count)\n\t}\n\tif agg.Min == nil {\n\t\tt.Fatalf(\"expected aggregation Min != nil; got: %v\", agg.Min)\n\t}\n\tif *agg.Min != float64(60) {\n\t\tt.Fatalf(\"expected aggregation Min = %v; got: %v\", float64(60), *agg.Min)\n\t}\n\tif agg.Max == nil {\n\t\tt.Fatalf(\"expected aggregation Max != nil; got: %v\", agg.Max)\n\t}\n\tif *agg.Max != float64(98) {\n\t\tt.Fatalf(\"expected aggregation Max = %v; got: %v\", float64(98), *agg.Max)\n\t}\n\tif agg.Avg == nil {\n\t\tt.Fatalf(\"expected aggregation Avg != nil; got: %v\", agg.Avg)\n\t}\n\tif *agg.Avg != float64(78.5) {\n\t\tt.Fatalf(\"expected aggregation Avg = %v; got: %v\", float64(78.5), *agg.Avg)\n\t}\n\tif agg.Sum == nil {\n\t\tt.Fatalf(\"expected aggregation Sum != nil; got: %v\", agg.Sum)\n\t}\n\tif *agg.Sum != float64(471) {\n\t\tt.Fatalf(\"expected aggregation Sum = %v; got: %v\", float64(471), *agg.Sum)\n\t}\n}\n\nfunc TestAggsMetricsExtendedStats(t *testing.T) {\n\ts := `{\n\t\"grades_stats\": {\n    \"count\": 6,\n    \"min\": 72,\n    \"max\": 117.6,\n    \"avg\": 94.2,\n    \"sum\": 565.2,\n    \"sum_of_squares\": 54551.51999999999,\n    \"variance\": 218.2799999999976,\n    \"std_deviation\": 14.774302013969987\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.ExtendedStats(\"grades_stats\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Count != int64(6) {\n\t\tt.Fatalf(\"expected aggregation Count = %v; got: %v\", int64(6), agg.Count)\n\t}\n\tif agg.Min == nil {\n\t\tt.Fatalf(\"expected aggregation Min != nil; got: %v\", agg.Min)\n\t}\n\tif *agg.Min != float64(72) {\n\t\tt.Fatalf(\"expected aggregation Min = %v; got: %v\", float64(72), *agg.Min)\n\t}\n\tif agg.Max == nil {\n\t\tt.Fatalf(\"expected aggregation Max != nil; got: %v\", agg.Max)\n\t}\n\tif *agg.Max != float64(117.6) {\n\t\tt.Fatalf(\"expected aggregation Max = %v; got: %v\", float64(117.6), *agg.Max)\n\t}\n\tif agg.Avg == nil {\n\t\tt.Fatalf(\"expected aggregation Avg != nil; got: %v\", agg.Avg)\n\t}\n\tif *agg.Avg != float64(94.2) {\n\t\tt.Fatalf(\"expected aggregation Avg = %v; got: %v\", float64(94.2), *agg.Avg)\n\t}\n\tif agg.Sum == nil {\n\t\tt.Fatalf(\"expected aggregation Sum != nil; got: %v\", agg.Sum)\n\t}\n\tif *agg.Sum != float64(565.2) {\n\t\tt.Fatalf(\"expected aggregation Sum = %v; got: %v\", float64(565.2), *agg.Sum)\n\t}\n\tif agg.SumOfSquares == nil {\n\t\tt.Fatalf(\"expected aggregation sum_of_squares != nil; got: %v\", agg.SumOfSquares)\n\t}\n\tif *agg.SumOfSquares != float64(54551.51999999999) {\n\t\tt.Fatalf(\"expected aggregation sum_of_squares = %v; got: %v\", float64(54551.51999999999), *agg.SumOfSquares)\n\t}\n\tif agg.Variance == nil {\n\t\tt.Fatalf(\"expected aggregation Variance != nil; got: %v\", agg.Variance)\n\t}\n\tif *agg.Variance != float64(218.2799999999976) {\n\t\tt.Fatalf(\"expected aggregation Variance = %v; got: %v\", float64(218.2799999999976), *agg.Variance)\n\t}\n\tif agg.StdDeviation == nil {\n\t\tt.Fatalf(\"expected aggregation StdDeviation != nil; got: %v\", agg.StdDeviation)\n\t}\n\tif *agg.StdDeviation != float64(14.774302013969987) {\n\t\tt.Fatalf(\"expected aggregation StdDeviation = %v; got: %v\", float64(14.774302013969987), *agg.StdDeviation)\n\t}\n}\n\nfunc TestAggsMatrixStats(t *testing.T) {\n\ts := `{\n\t\"matrixstats\": {\n\t\t\"fields\": [{\n\t\t\t\"name\": \"income\",\n\t\t\t\"count\": 50,\n\t\t\t\"mean\": 51985.1,\n\t\t\t\"variance\": 7.383377037755103E7,\n\t\t\t\"skewness\": 0.5595114003506483,\n\t\t\t\"kurtosis\": 2.5692365287787124,\n\t\t\t\"covariance\": {\n\t\t\t\t\"income\": 7.383377037755103E7,\n\t\t\t\t\"poverty\": -21093.65836734694\n\t\t\t},\n\t\t\t\"correlation\": {\n\t\t\t\t\"income\": 1.0,\n\t\t\t\t\"poverty\": -0.8352655256272504\n\t\t\t}\n\t\t}, {\n\t\t\t\"name\": \"poverty\",\n\t\t\t\"count\": 51,\n\t\t\t\"mean\": 12.732000000000001,\n\t\t\t\"variance\": 8.637730612244896,\n\t\t\t\"skewness\": 0.4516049811903419,\n\t\t\t\"kurtosis\": 2.8615929677997767,\n\t\t\t\"covariance\": {\n\t\t\t\t\"income\": -21093.65836734694,\n\t\t\t\t\"poverty\": 8.637730612244896\n\t\t\t},\n\t\t\t\"correlation\": {\n\t\t\t\t\"income\": -0.8352655256272504,\n\t\t\t\t\"poverty\": 1.0\n\t\t\t}\n\t\t}]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.MatrixStats(\"matrixstats\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif want, got := 2, len(agg.Fields); want != got {\n\t\tt.Fatalf(\"expected aggregaton len(Fields) = %v; got: %v\", want, got)\n\t}\n\tfield := agg.Fields[0]\n\tif want, got := \"income\", field.Name; want != got {\n\t\tt.Fatalf(\"expected aggregation field name == %q; got: %q\", want, got)\n\t}\n\tif want, got := int64(50), field.Count; want != got {\n\t\tt.Fatalf(\"expected aggregation field count == %v; got: %v\", want, got)\n\t}\n\tif want, got := 51985.1, field.Mean; want != got {\n\t\tt.Fatalf(\"expected aggregation field mean == %v; got: %v\", want, got)\n\t}\n\tif want, got := 7.383377037755103e7, field.Variance; want != got {\n\t\tt.Fatalf(\"expected aggregation field variance == %v; got: %v\", want, got)\n\t}\n\tif want, got := 0.5595114003506483, field.Skewness; want != got {\n\t\tt.Fatalf(\"expected aggregation field skewness == %v; got: %v\", want, got)\n\t}\n\tif want, got := 2.5692365287787124, field.Kurtosis; want != got {\n\t\tt.Fatalf(\"expected aggregation field kurtosis == %v; got: %v\", want, got)\n\t}\n\tif field.Covariance == nil {\n\t\tt.Fatalf(\"expected aggregation field covariance != nil; got: %v\", nil)\n\t}\n\tif want, got := 7.383377037755103e7, field.Covariance[\"income\"]; want != got {\n\t\tt.Fatalf(\"expected aggregation field covariance == %v; got: %v\", want, got)\n\t}\n\tif want, got := -21093.65836734694, field.Covariance[\"poverty\"]; want != got {\n\t\tt.Fatalf(\"expected aggregation field covariance == %v; got: %v\", want, got)\n\t}\n\tif field.Correlation == nil {\n\t\tt.Fatalf(\"expected aggregation field correlation != nil; got: %v\", nil)\n\t}\n\tif want, got := 1.0, field.Correlation[\"income\"]; want != got {\n\t\tt.Fatalf(\"expected aggregation field correlation == %v; got: %v\", want, got)\n\t}\n\tif want, got := -0.8352655256272504, field.Correlation[\"poverty\"]; want != got {\n\t\tt.Fatalf(\"expected aggregation field correlation == %v; got: %v\", want, got)\n\t}\n\tfield = agg.Fields[1]\n\tif want, got := \"poverty\", field.Name; want != got {\n\t\tt.Fatalf(\"expected aggregation field name == %q; got: %q\", want, got)\n\t}\n\tif want, got := int64(51), field.Count; want != got {\n\t\tt.Fatalf(\"expected aggregation field count == %v; got: %v\", want, got)\n\t}\n}\n\nfunc TestAggsMetricsPercentiles(t *testing.T) {\n\ts := `{\n  \"load_time_outlier\": {\n\t\t\"values\" : {\n\t\t  \"1.0\": 15,\n\t\t  \"5.0\": 20,\n\t\t  \"25.0\": 23,\n\t\t  \"50.0\": 25,\n\t\t  \"75.0\": 29,\n\t\t  \"95.0\": 60,\n\t\t  \"99.0\": 150\n\t\t}\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Percentiles(\"load_time_outlier\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Values == nil {\n\t\tt.Fatalf(\"expected aggregation Values != nil; got: %v\", agg.Values)\n\t}\n\tif len(agg.Values) != 7 {\n\t\tt.Fatalf(\"expected %d aggregation Values; got: %d\", 7, len(agg.Values))\n\t}\n\tif agg.Values[\"1.0\"] != float64(15) {\n\t\tt.Errorf(\"expected aggregation value for \\\"1.0\\\" = %v; got: %v\", float64(15), agg.Values[\"1.0\"])\n\t}\n\tif agg.Values[\"5.0\"] != float64(20) {\n\t\tt.Errorf(\"expected aggregation value for \\\"5.0\\\" = %v; got: %v\", float64(20), agg.Values[\"5.0\"])\n\t}\n\tif agg.Values[\"25.0\"] != float64(23) {\n\t\tt.Errorf(\"expected aggregation value for \\\"25.0\\\" = %v; got: %v\", float64(23), agg.Values[\"25.0\"])\n\t}\n\tif agg.Values[\"50.0\"] != float64(25) {\n\t\tt.Errorf(\"expected aggregation value for \\\"50.0\\\" = %v; got: %v\", float64(25), agg.Values[\"50.0\"])\n\t}\n\tif agg.Values[\"75.0\"] != float64(29) {\n\t\tt.Errorf(\"expected aggregation value for \\\"75.0\\\" = %v; got: %v\", float64(29), agg.Values[\"75.0\"])\n\t}\n\tif agg.Values[\"95.0\"] != float64(60) {\n\t\tt.Errorf(\"expected aggregation value for \\\"95.0\\\" = %v; got: %v\", float64(60), agg.Values[\"95.0\"])\n\t}\n\tif agg.Values[\"99.0\"] != float64(150) {\n\t\tt.Errorf(\"expected aggregation value for \\\"99.0\\\" = %v; got: %v\", float64(150), agg.Values[\"99.0\"])\n\t}\n}\n\nfunc TestAggsMetricsPercentileRanks(t *testing.T) {\n\ts := `{\n  \"load_time_outlier\": {\n\t\t\"values\" : {\n\t\t  \"15\": 92,\n\t\t  \"30\": 100\n\t\t}\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.PercentileRanks(\"load_time_outlier\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Values == nil {\n\t\tt.Fatalf(\"expected aggregation Values != nil; got: %v\", agg.Values)\n\t}\n\tif len(agg.Values) != 2 {\n\t\tt.Fatalf(\"expected %d aggregation Values; got: %d\", 7, len(agg.Values))\n\t}\n\tif agg.Values[\"15\"] != float64(92) {\n\t\tt.Errorf(\"expected aggregation value for \\\"15\\\" = %v; got: %v\", float64(92), agg.Values[\"15\"])\n\t}\n\tif agg.Values[\"30\"] != float64(100) {\n\t\tt.Errorf(\"expected aggregation value for \\\"30\\\" = %v; got: %v\", float64(100), agg.Values[\"30\"])\n\t}\n}\n\nfunc TestAggsMetricsTopHits(t *testing.T) {\n\ts := `{\n  \"top-tags\": {\n     \"buckets\": [\n        {\n           \"key\": \"windows-7\",\n           \"doc_count\": 25365,\n           \"top_tags_hits\": {\n              \"hits\": {\n                 \"total\": {\n                   \"value\": 25365,\n                   \"relation\": \"eq\"\n                 },\n                 \"max_score\": 1,\n                 \"hits\": [\n                    {\n                       \"_index\": \"stack\",\n                       \"_type\": \"question\",\n                       \"_id\": \"602679\",\n                       \"_score\": 1,\n                       \"_source\": {\n                          \"title\": \"Windows port opening\"\n                       },\n                       \"sort\": [\n                          1370143231177\n                       ]\n                    }\n                 ]\n              }\n           }\n        },\n        {\n           \"key\": \"linux\",\n           \"doc_count\": 18342,\n           \"top_tags_hits\": {\n              \"hits\": {\n                 \"total\": {\n                   \"value\": 18342,\n                   \"relation\": \"eq\"\n                 },\n                 \"max_score\": 1,\n                 \"hits\": [\n                    {\n                       \"_index\": \"stack\",\n                       \"_type\": \"question\",\n                       \"_id\": \"602672\",\n                       \"_score\": 1,\n                       \"_source\": {\n                          \"title\": \"Ubuntu RFID Screensaver lock-unlock\"\n                       },\n                       \"sort\": [\n                          1370143379747\n                       ]\n                    }\n                 ]\n              }\n           }\n        },\n        {\n           \"key\": \"windows\",\n           \"doc_count\": 18119,\n           \"top_tags_hits\": {\n              \"hits\": {\n                 \"total\": {\n                   \"value\": 18119,\n                   \"relation\": \"eq\"\n                 },\n                 \"max_score\": 1,\n                 \"hits\": [\n                    {\n                       \"_index\": \"stack\",\n                       \"_type\": \"question\",\n                       \"_id\": \"602678\",\n                       \"_score\": 1,\n                       \"_source\": {\n                          \"title\": \"If I change my computers date / time, what could be affected?\"\n                       },\n                       \"sort\": [\n                          1370142868283\n                       ]\n                    }\n                 ]\n              }\n           }\n        }\n     ]\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Terms(\"top-tags\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 3 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 3, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].Key != \"windows-7\" {\n\t\tt.Errorf(\"expected bucket key = %q; got: %q\", \"windows-7\", agg.Buckets[0].Key)\n\t}\n\tif agg.Buckets[1].Key != \"linux\" {\n\t\tt.Errorf(\"expected bucket key = %q; got: %q\", \"linux\", agg.Buckets[1].Key)\n\t}\n\tif agg.Buckets[2].Key != \"windows\" {\n\t\tt.Errorf(\"expected bucket key = %q; got: %q\", \"windows\", agg.Buckets[2].Key)\n\t}\n\n\t// Sub-aggregation of top-hits\n\tsubAgg, found := agg.Buckets[0].TopHits(\"top_tags_hits\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub aggregation != nil; got: %v\", subAgg)\n\t}\n\tif subAgg.Hits == nil {\n\t\tt.Fatalf(\"expected sub aggregation Hits != nil; got: %v\", subAgg.Hits)\n\t}\n\tif subAgg.Hits.TotalHits == nil {\n\t\tt.Fatalf(\"expected sub aggregation Hits.TotalHits != nil; got: %v\", subAgg.Hits.TotalHits)\n\t}\n\tif subAgg.Hits.TotalHits.Value != 25365 {\n\t\tt.Fatalf(\"expected sub aggregation Hits.TotalHits.Value = %d; got: %d\", 25365, subAgg.Hits.TotalHits.Value)\n\t}\n\tif subAgg.Hits.TotalHits.Relation != \"eq\" {\n\t\tt.Fatalf(\"expected sub aggregation Hits.TotalHits.Relation = %v; got: %v\", \"eq\", subAgg.Hits.TotalHits.Relation)\n\t}\n\tif subAgg.Hits.MaxScore == nil {\n\t\tt.Fatalf(\"expected sub aggregation Hits.MaxScore != %v; got: %v\", nil, *subAgg.Hits.MaxScore)\n\t}\n\tif *subAgg.Hits.MaxScore != float64(1.0) {\n\t\tt.Fatalf(\"expected sub aggregation Hits.MaxScore = %v; got: %v\", float64(1.0), *subAgg.Hits.MaxScore)\n\t}\n\n\tsubAgg, found = agg.Buckets[1].TopHits(\"top_tags_hits\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub aggregation != nil; got: %v\", subAgg)\n\t}\n\tif subAgg.Hits == nil {\n\t\tt.Fatalf(\"expected sub aggregation Hits != nil; got: %v\", subAgg.Hits)\n\t}\n\tif subAgg.Hits.TotalHits == nil {\n\t\tt.Fatalf(\"expected sub aggregation Hits.TotalHits != nil; got: %v\", subAgg.Hits.TotalHits)\n\t}\n\tif subAgg.Hits.TotalHits.Value != 18342 {\n\t\tt.Fatalf(\"expected sub aggregation Hits.TotalHits.Value = %d; got: %d\", 18342, subAgg.Hits.TotalHits.Value)\n\t}\n\tif subAgg.Hits.TotalHits.Relation != \"eq\" {\n\t\tt.Fatalf(\"expected sub aggregation Hits.TotalHits.Relation = %v; got: %v\", \"eq\", subAgg.Hits.TotalHits.Relation)\n\t}\n\tif subAgg.Hits.MaxScore == nil {\n\t\tt.Fatalf(\"expected sub aggregation Hits.MaxScore != %v; got: %v\", nil, *subAgg.Hits.MaxScore)\n\t}\n\tif *subAgg.Hits.MaxScore != float64(1.0) {\n\t\tt.Fatalf(\"expected sub aggregation Hits.MaxScore = %v; got: %v\", float64(1.0), *subAgg.Hits.MaxScore)\n\t}\n\n\tsubAgg, found = agg.Buckets[2].TopHits(\"top_tags_hits\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub aggregation != nil; got: %v\", subAgg)\n\t}\n\tif subAgg.Hits == nil {\n\t\tt.Fatalf(\"expected sub aggregation Hits != nil; got: %v\", subAgg.Hits)\n\t}\n\tif subAgg.Hits.TotalHits == nil {\n\t\tt.Fatalf(\"expected sub aggregation Hits.TotalHits != nil; got: %v\", subAgg.Hits.TotalHits)\n\t}\n\tif subAgg.Hits.TotalHits.Value != 18119 {\n\t\tt.Fatalf(\"expected sub aggregation Hits.TotalHits.Value = %d; got: %d\", 18119, subAgg.Hits.TotalHits.Value)\n\t}\n\tif subAgg.Hits.TotalHits.Relation != \"eq\" {\n\t\tt.Fatalf(\"expected sub aggregation Hits.TotalHits.Relation = %v; got: %v\", \"eq\", subAgg.Hits.TotalHits.Relation)\n\t}\n\tif subAgg.Hits.MaxScore == nil {\n\t\tt.Fatalf(\"expected sub aggregation Hits.MaxScore != %v; got: %v\", nil, *subAgg.Hits.MaxScore)\n\t}\n\tif *subAgg.Hits.MaxScore != float64(1.0) {\n\t\tt.Fatalf(\"expected sub aggregation Hits.MaxScore = %v; got: %v\", float64(1.0), *subAgg.Hits.MaxScore)\n\t}\n}\n\nfunc TestAggsBucketGlobal(t *testing.T) {\n\ts := `{\n\t\"all_products\" : {\n    \"doc_count\" : 100,\n\t\t\"avg_price\" : {\n\t\t\t\"value\" : 56.3\n\t\t}\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Global(\"all_products\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.DocCount != 100 {\n\t\tt.Fatalf(\"expected aggregation DocCount = %d; got: %d\", 100, agg.DocCount)\n\t}\n\n\t// Sub-aggregation\n\tsubAgg, found := agg.Avg(\"avg_price\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub-aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub-aggregation != nil; got: %v\", subAgg)\n\t}\n\tif subAgg.Value == nil {\n\t\tt.Fatalf(\"expected sub-aggregation value != nil; got: %v\", subAgg.Value)\n\t}\n\tif *subAgg.Value != float64(56.3) {\n\t\tt.Fatalf(\"expected sub-aggregation value = %v; got: %v\", float64(56.3), *subAgg.Value)\n\t}\n}\n\nfunc TestAggsBucketFilter(t *testing.T) {\n\ts := `{\n\t\"in_stock_products\" : {\n\t  \"doc_count\" : 100,\n\t  \"avg_price\" : { \"value\" : 56.3 }\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Filter(\"in_stock_products\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.DocCount != 100 {\n\t\tt.Fatalf(\"expected aggregation DocCount = %d; got: %d\", 100, agg.DocCount)\n\t}\n\n\t// Sub-aggregation\n\tsubAgg, found := agg.Avg(\"avg_price\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub-aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub-aggregation != nil; got: %v\", subAgg)\n\t}\n\tif subAgg.Value == nil {\n\t\tt.Fatalf(\"expected sub-aggregation value != nil; got: %v\", subAgg.Value)\n\t}\n\tif *subAgg.Value != float64(56.3) {\n\t\tt.Fatalf(\"expected sub-aggregation value = %v; got: %v\", float64(56.3), *subAgg.Value)\n\t}\n}\n\nfunc TestAggsBucketFiltersWithBuckets(t *testing.T) {\n\ts := `{\n  \"messages\" : {\n    \"buckets\" : [\n    \t{\n        \"doc_count\" : 34,\n        \"monthly\" : {\n          \"buckets\" : []\n        }\n      },\n      {\n        \"doc_count\" : 439,\n        \"monthly\" : {\n          \"buckets\" : []\n        }\n      }\n    ]\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Filters(\"messages\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != %v; got: %v\", nil, agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Fatalf(\"expected %d buckets; got: %d\", 2, len(agg.Buckets))\n\t}\n\n\tif agg.Buckets[0].DocCount != 34 {\n\t\tt.Fatalf(\"expected DocCount = %d; got: %d\", 34, agg.Buckets[0].DocCount)\n\t}\n\tsubAgg, found := agg.Buckets[0].Histogram(\"monthly\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub aggregation != %v; got: %v\", nil, subAgg)\n\t}\n\n\tif agg.Buckets[1].DocCount != 439 {\n\t\tt.Fatalf(\"expected DocCount = %d; got: %d\", 439, agg.Buckets[1].DocCount)\n\t}\n\tsubAgg, found = agg.Buckets[1].Histogram(\"monthly\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub aggregation != %v; got: %v\", nil, subAgg)\n\t}\n}\n\nfunc TestAggsBucketFiltersWithNamedBuckets(t *testing.T) {\n\ts := `{\n  \"messages\" : {\n    \"buckets\" : {\n      \"errors\" : {\n        \"doc_count\" : 34,\n        \"monthly\" : {\n          \"buckets\" : []\n        }\n      },\n      \"warnings\" : {\n        \"doc_count\" : 439,\n        \"monthly\" : {\n          \"buckets\" : []\n        }\n      }\n    }\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Filters(\"messages\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.NamedBuckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != %v; got: %v\", nil, agg.NamedBuckets)\n\t}\n\tif len(agg.NamedBuckets) != 2 {\n\t\tt.Fatalf(\"expected %d buckets; got: %d\", 2, len(agg.NamedBuckets))\n\t}\n\n\tif agg.NamedBuckets[\"errors\"].DocCount != 34 {\n\t\tt.Fatalf(\"expected DocCount = %d; got: %d\", 34, agg.NamedBuckets[\"errors\"].DocCount)\n\t}\n\tsubAgg, found := agg.NamedBuckets[\"errors\"].Histogram(\"monthly\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub aggregation != %v; got: %v\", nil, subAgg)\n\t}\n\n\tif agg.NamedBuckets[\"warnings\"].DocCount != 439 {\n\t\tt.Fatalf(\"expected DocCount = %d; got: %d\", 439, agg.NamedBuckets[\"warnings\"].DocCount)\n\t}\n\tsubAgg, found = agg.NamedBuckets[\"warnings\"].Histogram(\"monthly\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub aggregation != %v; got: %v\", nil, subAgg)\n\t}\n}\n\nfunc TestAggsBucketAdjacencyMatrix(t *testing.T) {\n\ts := `{\n\t\"interactions\": {\n\t\t\"buckets\": [\n\t\t\t{\n\t\t\t\t\"key\": \"grpA\",\n\t\t\t\t\"doc_count\": 2,\n\t\t\t\t\"monthly\": {\n\t\t\t\t\t\"buckets\": []\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"key\": \"grpA&grpB\",\n\t\t\t\t\"doc_count\": 1,\n\t\t\t\t\"monthly\": {\n\t\t\t\t\t\"buckets\": []\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.AdjacencyMatrix(\"interactions\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != %v; got: %v\", nil, agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Fatalf(\"expected %d buckets; got: %d\", 2, len(agg.Buckets))\n\t}\n\n\tif agg.Buckets[0].DocCount != 2 {\n\t\tt.Fatalf(\"expected DocCount = %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t}\n\tsubAgg, found := agg.Buckets[0].Histogram(\"monthly\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub aggregation != %v; got: %v\", nil, subAgg)\n\t}\n\n\tif agg.Buckets[1].DocCount != 1 {\n\t\tt.Fatalf(\"expected DocCount = %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t}\n\tsubAgg, found = agg.Buckets[1].Histogram(\"monthly\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub aggregation != %v; got: %v\", nil, subAgg)\n\t}\n}\n\nfunc TestAggsBucketMissing(t *testing.T) {\n\ts := `{\n\t\"products_without_a_price\" : {\n\t\t\"doc_count\" : 10\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Missing(\"products_without_a_price\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.DocCount != 10 {\n\t\tt.Fatalf(\"expected aggregation DocCount = %d; got: %d\", 10, agg.DocCount)\n\t}\n}\n\nfunc TestAggsBucketNested(t *testing.T) {\n\ts := `{\n\t\"resellers\": {\n\t\t\"min_price\": {\n\t\t\t\"value\" : 350\n\t\t}\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Nested(\"resellers\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.DocCount != 0 {\n\t\tt.Fatalf(\"expected aggregation DocCount = %d; got: %d\", 0, agg.DocCount)\n\t}\n\n\t// Sub-aggregation\n\tsubAgg, found := agg.Avg(\"min_price\")\n\tif !found {\n\t\tt.Fatalf(\"expected sub-aggregation to be found; got: %v\", found)\n\t}\n\tif subAgg == nil {\n\t\tt.Fatalf(\"expected sub-aggregation != nil; got: %v\", subAgg)\n\t}\n\tif subAgg.Value == nil {\n\t\tt.Fatalf(\"expected sub-aggregation value != nil; got: %v\", subAgg.Value)\n\t}\n\tif *subAgg.Value != float64(350) {\n\t\tt.Fatalf(\"expected sub-aggregation value = %v; got: %v\", float64(350), *subAgg.Value)\n\t}\n}\n\nfunc TestAggsBucketReverseNested(t *testing.T) {\n\ts := `{\n\t\"comment_to_issue\": {\n\t\t\"doc_count\" : 10\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.ReverseNested(\"comment_to_issue\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.DocCount != 10 {\n\t\tt.Fatalf(\"expected aggregation DocCount = %d; got: %d\", 10, agg.DocCount)\n\t}\n}\n\nfunc TestAggsBucketChildren(t *testing.T) {\n\ts := `{\n\t\"to-answers\": {\n\t\t\"doc_count\" : 10\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Children(\"to-answers\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.DocCount != 10 {\n\t\tt.Fatalf(\"expected aggregation DocCount = %d; got: %d\", 10, agg.DocCount)\n\t}\n}\n\nfunc TestAggsBucketTerms(t *testing.T) {\n\ts := `{\n\t\"users\" : {\n\t  \"doc_count_error_upper_bound\" : 1,\n\t  \"sum_other_doc_count\" : 2,\n\t  \"buckets\" : [ {\n\t    \"key\" : \"olivere\",\n\t    \"doc_count\" : 2\n\t  }, {\n\t    \"key\" : \"sandrae\",\n\t    \"doc_count\" : 1\n\t  } ]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Terms(\"users\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 2, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].Key != \"olivere\" {\n\t\tt.Errorf(\"expected key %q; got: %q\", \"olivere\", agg.Buckets[0].Key)\n\t}\n\tif agg.Buckets[0].DocCount != 2 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].Key != \"sandrae\" {\n\t\tt.Errorf(\"expected key %q; got: %q\", \"sandrae\", agg.Buckets[1].Key)\n\t}\n\tif agg.Buckets[1].DocCount != 1 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t}\n}\n\nfunc TestAggsBucketTermsWithNumericKeys(t *testing.T) {\n\ts := `{\n\t\"users\" : {\n\t  \"doc_count_error_upper_bound\" : 1,\n\t  \"sum_other_doc_count\" : 2,\n\t  \"buckets\" : [ {\n\t    \"key\" : 17,\n\t    \"doc_count\" : 2\n\t  }, {\n\t    \"key\" : 21,\n\t    \"doc_count\" : 1\n\t  } ]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Terms(\"users\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 2, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].Key != float64(17) {\n\t\tt.Errorf(\"expected key %v; got: %v\", 17, agg.Buckets[0].Key)\n\t}\n\tif got, err := agg.Buckets[0].KeyNumber.Int64(); err != nil {\n\t\tt.Errorf(\"expected to convert key to int64; got: %v\", err)\n\t} else if got != 17 {\n\t\tt.Errorf(\"expected key %v; got: %v\", 17, agg.Buckets[0].Key)\n\t}\n\tif agg.Buckets[0].DocCount != 2 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].Key != float64(21) {\n\t\tt.Errorf(\"expected key %v; got: %v\", 21, agg.Buckets[1].Key)\n\t}\n\tif got, err := agg.Buckets[1].KeyNumber.Int64(); err != nil {\n\t\tt.Errorf(\"expected to convert key to int64; got: %v\", err)\n\t} else if got != 21 {\n\t\tt.Errorf(\"expected key %v; got: %v\", 21, agg.Buckets[1].Key)\n\t}\n\tif agg.Buckets[1].DocCount != 1 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t}\n}\n\nfunc TestAggsBucketTermsWithBoolKeys(t *testing.T) {\n\ts := `{\n\t\"users\" : {\n\t  \"doc_count_error_upper_bound\" : 1,\n\t  \"sum_other_doc_count\" : 2,\n\t  \"buckets\" : [ {\n\t    \"key\" : true,\n\t    \"doc_count\" : 2\n\t  }, {\n\t    \"key\" : false,\n\t    \"doc_count\" : 1\n\t  } ]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Terms(\"users\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 2, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].Key != true {\n\t\tt.Errorf(\"expected key %v; got: %v\", true, agg.Buckets[0].Key)\n\t}\n\tif agg.Buckets[0].DocCount != 2 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].Key != false {\n\t\tt.Errorf(\"expected key %v; got: %v\", false, agg.Buckets[1].Key)\n\t}\n\tif agg.Buckets[1].DocCount != 1 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t}\n}\n\nfunc TestAggsBucketSignificantTerms(t *testing.T) {\n\ts := `{\n\t\"significantCrimeTypes\" : {\n    \"doc_count\": 47347,\n    \"buckets\" : [\n      {\n        \"key\": \"Bicycle theft\",\n        \"doc_count\": 3640,\n        \"score\": 0.371235374214817,\n        \"bg_count\": 66799\n      }\n    ]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.SignificantTerms(\"significantCrimeTypes\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.DocCount != 47347 {\n\t\tt.Fatalf(\"expected aggregation DocCount != %d; got: %d\", 47347, agg.DocCount)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 1 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 1, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].Key != \"Bicycle theft\" {\n\t\tt.Errorf(\"expected key = %q; got: %q\", \"Bicycle theft\", agg.Buckets[0].Key)\n\t}\n\tif agg.Buckets[0].DocCount != 3640 {\n\t\tt.Errorf(\"expected doc count = %d; got: %d\", 3640, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[0].Score != float64(0.371235374214817) {\n\t\tt.Errorf(\"expected score = %v; got: %v\", float64(0.371235374214817), agg.Buckets[0].Score)\n\t}\n\tif agg.Buckets[0].BgCount != 66799 {\n\t\tt.Errorf(\"expected BgCount = %d; got: %d\", 66799, agg.Buckets[0].BgCount)\n\t}\n}\n\nfunc TestAggsBucketSampler(t *testing.T) {\n\ts := `{\n\t\"sample\" : {\n    \"doc_count\": 1000,\n    \"keywords\": {\n    \t\"doc_count\": 1000,\n\t    \"buckets\" : [\n\t      {\n\t        \"key\": \"bend\",\n\t        \"doc_count\": 58,\n\t        \"score\": 37.982536582524276,\n\t        \"bg_count\": 103\n\t      }\n\t    ]\n    }\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Sampler(\"sample\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.DocCount != 1000 {\n\t\tt.Fatalf(\"expected aggregation DocCount != %d; got: %d\", 1000, agg.DocCount)\n\t}\n\tsub, found := agg.Aggregations[\"keywords\"]\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation %q\", \"keywords\")\n\t}\n\tif sub == nil {\n\t\tt.Fatalf(\"expected sub aggregation %q; got: %v\", \"keywords\", sub)\n\t}\n}\n\nfunc TestAggsBucketDiversifiedSampler(t *testing.T) {\n\ts := `{\n\t\"diversified_sampler\" : {\n    \"doc_count\": 1000,\n    \"keywords\": {\n    \t\"doc_count\": 1000,\n\t    \"buckets\" : [\n\t      {\n\t        \"key\": \"bend\",\n\t        \"doc_count\": 58,\n\t        \"score\": 37.982536582524276,\n\t        \"bg_count\": 103\n\t      }\n\t    ]\n    }\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.DiversifiedSampler(\"diversified_sampler\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.DocCount != 1000 {\n\t\tt.Fatalf(\"expected aggregation DocCount != %d; got: %d\", 1000, agg.DocCount)\n\t}\n\tsub, found := agg.Aggregations[\"keywords\"]\n\tif !found {\n\t\tt.Fatalf(\"expected sub aggregation %q\", \"keywords\")\n\t}\n\tif sub == nil {\n\t\tt.Fatalf(\"expected sub aggregation %q; got: %v\", \"keywords\", sub)\n\t}\n}\n\nfunc TestAggsBucketRange(t *testing.T) {\n\ts := `{\n\t\"price_ranges\" : {\n\t\t\"buckets\": [\n\t\t\t{\n\t\t\t\t\"to\": 50,\n\t\t\t\t\"doc_count\": 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"from\": 50,\n\t\t\t\t\"to\": 100,\n\t\t\t\t\"doc_count\": 4\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"from\": 100,\n\t\t\t\t\"doc_count\": 4\n\t\t\t}\n\t\t]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Range(\"price_ranges\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 3 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 3, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].From != nil {\n\t\tt.Errorf(\"expected From = %v; got: %v\", nil, agg.Buckets[0].From)\n\t}\n\tif agg.Buckets[0].To == nil {\n\t\tt.Errorf(\"expected To != %v; got: %v\", nil, agg.Buckets[0].To)\n\t}\n\tif *agg.Buckets[0].To != float64(50) {\n\t\tt.Errorf(\"expected To = %v; got: %v\", float64(50), *agg.Buckets[0].To)\n\t}\n\tif agg.Buckets[0].DocCount != 2 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].From == nil {\n\t\tt.Errorf(\"expected From != %v; got: %v\", nil, agg.Buckets[1].From)\n\t}\n\tif *agg.Buckets[1].From != float64(50) {\n\t\tt.Errorf(\"expected From = %v; got: %v\", float64(50), *agg.Buckets[1].From)\n\t}\n\tif agg.Buckets[1].To == nil {\n\t\tt.Errorf(\"expected To != %v; got: %v\", nil, agg.Buckets[1].To)\n\t}\n\tif *agg.Buckets[1].To != float64(100) {\n\t\tt.Errorf(\"expected To = %v; got: %v\", float64(100), *agg.Buckets[1].To)\n\t}\n\tif agg.Buckets[1].DocCount != 4 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 4, agg.Buckets[1].DocCount)\n\t}\n\tif agg.Buckets[2].From == nil {\n\t\tt.Errorf(\"expected From != %v; got: %v\", nil, agg.Buckets[2].From)\n\t}\n\tif *agg.Buckets[2].From != float64(100) {\n\t\tt.Errorf(\"expected From = %v; got: %v\", float64(100), *agg.Buckets[2].From)\n\t}\n\tif agg.Buckets[2].To != nil {\n\t\tt.Errorf(\"expected To = %v; got: %v\", nil, agg.Buckets[2].To)\n\t}\n\tif agg.Buckets[2].DocCount != 4 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 4, agg.Buckets[2].DocCount)\n\t}\n}\n\nfunc TestAggsBucketDateRange(t *testing.T) {\n\ts := `{\n\t\"range\": {\n\t\t\"buckets\": [\n\t\t\t{\n\t\t\t\t\"to\": 1.3437792E+12,\n\t\t\t\t\"to_as_string\": \"08-2012\",\n\t\t\t\t\"doc_count\": 7\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"from\": 1.3437792E+12,\n\t\t\t\t\"from_as_string\": \"08-2012\",\n\t\t\t\t\"doc_count\": 2\n\t\t\t}\n\t\t]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.DateRange(\"range\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 2, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].From != nil {\n\t\tt.Errorf(\"expected From = %v; got: %v\", nil, agg.Buckets[0].From)\n\t}\n\tif agg.Buckets[0].To == nil {\n\t\tt.Errorf(\"expected To != %v; got: %v\", nil, agg.Buckets[0].To)\n\t}\n\tif *agg.Buckets[0].To != float64(1.3437792e+12) {\n\t\tt.Errorf(\"expected To = %v; got: %v\", float64(1.3437792e+12), *agg.Buckets[0].To)\n\t}\n\tif agg.Buckets[0].ToAsString != \"08-2012\" {\n\t\tt.Errorf(\"expected ToAsString = %q; got: %q\", \"08-2012\", agg.Buckets[0].ToAsString)\n\t}\n\tif agg.Buckets[0].DocCount != 7 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 7, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].From == nil {\n\t\tt.Errorf(\"expected From != %v; got: %v\", nil, agg.Buckets[1].From)\n\t}\n\tif *agg.Buckets[1].From != float64(1.3437792e+12) {\n\t\tt.Errorf(\"expected From = %v; got: %v\", float64(1.3437792e+12), *agg.Buckets[1].From)\n\t}\n\tif agg.Buckets[1].FromAsString != \"08-2012\" {\n\t\tt.Errorf(\"expected FromAsString = %q; got: %q\", \"08-2012\", agg.Buckets[1].FromAsString)\n\t}\n\tif agg.Buckets[1].To != nil {\n\t\tt.Errorf(\"expected To = %v; got: %v\", nil, agg.Buckets[1].To)\n\t}\n\tif agg.Buckets[1].DocCount != 2 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 2, agg.Buckets[1].DocCount)\n\t}\n}\n\nfunc TestAggsBucketIPRange(t *testing.T) {\n\ts := `{\n\t\"ip_ranges\": {\n\t\t\"buckets\" : [\n\t\t\t{\n\t\t\t\t\"to\": 167772165,\n\t\t\t\t\"to_as_string\": \"10.0.0.5\",\n\t\t\t\t\"doc_count\": 4\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"from\": 167772165,\n\t\t\t\t\"from_as_string\": \"10.0.0.5\",\n\t\t\t\t\"doc_count\": 6\n\t\t\t}\n\t\t]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.IPRange(\"ip_ranges\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 2, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].From != nil {\n\t\tt.Errorf(\"expected From = %v; got: %v\", nil, agg.Buckets[0].From)\n\t}\n\tif agg.Buckets[0].To == nil {\n\t\tt.Errorf(\"expected To != %v; got: %v\", nil, agg.Buckets[0].To)\n\t}\n\tif *agg.Buckets[0].To != float64(167772165) {\n\t\tt.Errorf(\"expected To = %v; got: %v\", float64(167772165), *agg.Buckets[0].To)\n\t}\n\tif agg.Buckets[0].ToAsString != \"10.0.0.5\" {\n\t\tt.Errorf(\"expected ToAsString = %q; got: %q\", \"10.0.0.5\", agg.Buckets[0].ToAsString)\n\t}\n\tif agg.Buckets[0].DocCount != 4 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 4, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].From == nil {\n\t\tt.Errorf(\"expected From != %v; got: %v\", nil, agg.Buckets[1].From)\n\t}\n\tif *agg.Buckets[1].From != float64(167772165) {\n\t\tt.Errorf(\"expected From = %v; got: %v\", float64(167772165), *agg.Buckets[1].From)\n\t}\n\tif agg.Buckets[1].FromAsString != \"10.0.0.5\" {\n\t\tt.Errorf(\"expected FromAsString = %q; got: %q\", \"10.0.0.5\", agg.Buckets[1].FromAsString)\n\t}\n\tif agg.Buckets[1].To != nil {\n\t\tt.Errorf(\"expected To = %v; got: %v\", nil, agg.Buckets[1].To)\n\t}\n\tif agg.Buckets[1].DocCount != 6 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 6, agg.Buckets[1].DocCount)\n\t}\n}\n\nfunc TestAggsBucketHistogram(t *testing.T) {\n\ts := `{\n\t\"prices\" : {\n\t\t\"buckets\": [\n\t\t\t{\n\t\t\t\t\"key\": 0,\n\t\t\t\t\"doc_count\": 2\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"key\": 50,\n\t\t\t\t\"doc_count\": 4\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"key\": 150,\n\t\t\t\t\"doc_count\": 3\n\t\t\t}\n\t\t]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Histogram(\"prices\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 3 {\n\t\tt.Errorf(\"expected %d buckets; got: %d\", 3, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].Key != 0 {\n\t\tt.Errorf(\"expected key = %v; got: %v\", 0, agg.Buckets[0].Key)\n\t}\n\tif agg.Buckets[0].KeyAsString != nil {\n\t\tt.Fatalf(\"expected key_as_string = %v; got: %q\", nil, *agg.Buckets[0].KeyAsString)\n\t}\n\tif agg.Buckets[0].DocCount != 2 {\n\t\tt.Errorf(\"expected doc count = %d; got: %d\", 2, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].Key != 50 {\n\t\tt.Errorf(\"expected key = %v; got: %v\", 50, agg.Buckets[1].Key)\n\t}\n\tif agg.Buckets[1].KeyAsString != nil {\n\t\tt.Fatalf(\"expected key_as_string = %v; got: %q\", nil, *agg.Buckets[1].KeyAsString)\n\t}\n\tif agg.Buckets[1].DocCount != 4 {\n\t\tt.Errorf(\"expected doc count = %d; got: %d\", 4, agg.Buckets[1].DocCount)\n\t}\n\tif agg.Buckets[2].Key != 150 {\n\t\tt.Errorf(\"expected key = %v; got: %v\", 150, agg.Buckets[2].Key)\n\t}\n\tif agg.Buckets[2].KeyAsString != nil {\n\t\tt.Fatalf(\"expected key_as_string = %v; got: %q\", nil, *agg.Buckets[2].KeyAsString)\n\t}\n\tif agg.Buckets[2].DocCount != 3 {\n\t\tt.Errorf(\"expected doc count = %d; got: %d\", 3, agg.Buckets[2].DocCount)\n\t}\n}\n\nfunc TestAggsBucketDateHistogram(t *testing.T) {\n\ts := `{\n\t\"articles_over_time\": {\n\t  \"buckets\": [\n\t      {\n\t          \"key_as_string\": \"2013-02-02\",\n\t          \"key\": 1328140800000,\n\t          \"doc_count\": 1\n\t      },\n\t      {\n\t          \"key_as_string\": \"2013-03-02\",\n\t          \"key\": 1330646400000,\n\t          \"doc_count\": 2\n\t      }\n\t  ]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.DateHistogram(\"articles_over_time\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 2, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].Key != 1328140800000 {\n\t\tt.Errorf(\"expected key %v; got: %v\", 1328140800000, agg.Buckets[0].Key)\n\t}\n\tif agg.Buckets[0].KeyAsString == nil {\n\t\tt.Fatalf(\"expected key_as_string != nil; got: %v\", agg.Buckets[0].KeyAsString)\n\t}\n\tif *agg.Buckets[0].KeyAsString != \"2013-02-02\" {\n\t\tt.Errorf(\"expected key_as_string %q; got: %q\", \"2013-02-02\", *agg.Buckets[0].KeyAsString)\n\t}\n\tif agg.Buckets[0].DocCount != 1 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 1, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].Key != 1330646400000 {\n\t\tt.Errorf(\"expected key %v; got: %v\", 1330646400000, agg.Buckets[1].Key)\n\t}\n\tif agg.Buckets[1].KeyAsString == nil {\n\t\tt.Fatalf(\"expected key_as_string != nil; got: %v\", agg.Buckets[1].KeyAsString)\n\t}\n\tif *agg.Buckets[1].KeyAsString != \"2013-03-02\" {\n\t\tt.Errorf(\"expected key_as_string %q; got: %q\", \"2013-03-02\", *agg.Buckets[1].KeyAsString)\n\t}\n\tif agg.Buckets[1].DocCount != 2 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 2, agg.Buckets[1].DocCount)\n\t}\n}\n\nfunc TestAggsMetricsGeoBounds(t *testing.T) {\n\ts := `{\n  \"viewport\": {\n    \"bounds\": {\n      \"top_left\": {\n        \"lat\": 80.45,\n        \"lon\": -160.22\n      },\n      \"bottom_right\": {\n        \"lat\": 40.65,\n        \"lon\": 42.57\n      }\n    }\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.GeoBounds(\"viewport\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Bounds.TopLeft.Latitude != float64(80.45) {\n\t\tt.Fatalf(\"expected Bounds.TopLeft.Latitude != %v; got: %v\", float64(80.45), agg.Bounds.TopLeft.Latitude)\n\t}\n\tif agg.Bounds.TopLeft.Longitude != float64(-160.22) {\n\t\tt.Fatalf(\"expected Bounds.TopLeft.Longitude != %v; got: %v\", float64(-160.22), agg.Bounds.TopLeft.Longitude)\n\t}\n\tif agg.Bounds.BottomRight.Latitude != float64(40.65) {\n\t\tt.Fatalf(\"expected Bounds.BottomRight.Latitude != %v; got: %v\", float64(40.65), agg.Bounds.BottomRight.Latitude)\n\t}\n\tif agg.Bounds.BottomRight.Longitude != float64(42.57) {\n\t\tt.Fatalf(\"expected Bounds.BottomRight.Longitude != %v; got: %v\", float64(42.57), agg.Bounds.BottomRight.Longitude)\n\t}\n}\n\nfunc TestAggsBucketGeoHash(t *testing.T) {\n\ts := `{\n\t\"myLarge-GrainGeoHashGrid\": {\n\t\t\"buckets\": [\n\t\t\t{\n\t\t\t\t\"key\": \"svz\",\n\t\t\t\t\"doc_count\": 10964\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"key\": \"sv8\",\n\t\t\t\t\"doc_count\": 3198\n\t\t\t}\n\t\t]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.GeoHash(\"myLarge-GrainGeoHashGrid\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 2, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].Key != \"svz\" {\n\t\tt.Errorf(\"expected key %q; got: %q\", \"svz\", agg.Buckets[0].Key)\n\t}\n\tif agg.Buckets[0].DocCount != 10964 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 10964, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].Key != \"sv8\" {\n\t\tt.Errorf(\"expected key %q; got: %q\", \"sv8\", agg.Buckets[1].Key)\n\t}\n\tif agg.Buckets[1].DocCount != 3198 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 3198, agg.Buckets[1].DocCount)\n\t}\n}\n\nfunc TestAggsBucketGeoTileGrid(t *testing.T) {\n\ts := `{\n\t\"geotile-grid-aggregation\":{\n\t\t\"buckets\":[\n\t\t\t{\n\t\t\t\t\"key\": \"6/38/20\",\n\t\t\t\t\"doc_count\": 36914\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"key\": \"6/38/19\",\n\t\t\t\t\"doc_count\": 22182\n\t\t\t}\n\t\t]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.GeoTile(\"geotile-grid-aggregation\")\n\tif !found {\n\t\tt.Fatal(\"expected aggregation to be found\")\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 2 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 2, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].Key != \"6/38/20\" {\n\t\tt.Errorf(\"expected key %q; got: %q\", \"6/38/20\", agg.Buckets[0].Key)\n\t}\n\tif agg.Buckets[0].DocCount != 36914 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 36914, agg.Buckets[0].DocCount)\n\t}\n\tif agg.Buckets[1].Key != \"6/38/19\" {\n\t\tt.Errorf(\"expected key %q; got: %q\", \"6/38/19\", agg.Buckets[1].Key)\n\t}\n\tif agg.Buckets[1].DocCount != 22182 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 22182, agg.Buckets[1].DocCount)\n\t}\n}\n\nfunc TestAggsMetricsGeoCentroid(t *testing.T) {\n\ts := `{\n  \"centroid\": {\n    \"location\": {\n\t\t\"lat\": 80.45,\n\t\t\"lon\": -160.22\n    },\n\t\"count\": 6\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.GeoCentroid(\"centroid\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Location.Latitude != float64(80.45) {\n\t\tt.Fatalf(\"expected Location.Latitude != %v; got: %v\", float64(80.45), agg.Location.Latitude)\n\t}\n\tif agg.Location.Longitude != float64(-160.22) {\n\t\tt.Fatalf(\"expected Location.Longitude != %v; got: %v\", float64(-160.22), agg.Location.Longitude)\n\t}\n\tif agg.Count != int(6) {\n\t\tt.Fatalf(\"expected Count != %v; got: %v\", int(6), agg.Count)\n\t}\n}\n\nfunc TestAggsBucketGeoDistance(t *testing.T) {\n\ts := `{\n\t\"rings\" : {\n\t\t\"buckets\": [\n\t\t\t{\n\t\t\t\t\"unit\": \"km\",\n\t\t\t\t\"to\": 100.0,\n\t\t\t\t\"doc_count\": 3\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"unit\": \"km\",\n\t\t\t\t\"from\": 100.0,\n\t\t\t\t\"to\": 300.0,\n\t\t\t\t\"doc_count\": 1\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"unit\": \"km\",\n\t\t\t\t\"from\": 300.0,\n\t\t\t\t\"doc_count\": 7\n\t\t\t}\n\t\t]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.GeoDistance(\"rings\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Buckets == nil {\n\t\tt.Fatalf(\"expected aggregation buckets != nil; got: %v\", agg.Buckets)\n\t}\n\tif len(agg.Buckets) != 3 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 3, len(agg.Buckets))\n\t}\n\tif agg.Buckets[0].From != nil {\n\t\tt.Errorf(\"expected From = %v; got: %v\", nil, agg.Buckets[0].From)\n\t}\n\tif agg.Buckets[0].To == nil {\n\t\tt.Errorf(\"expected To != %v; got: %v\", nil, agg.Buckets[0].To)\n\t}\n\tif *agg.Buckets[0].To != float64(100.0) {\n\t\tt.Errorf(\"expected To = %v; got: %v\", float64(100.0), *agg.Buckets[0].To)\n\t}\n\tif agg.Buckets[0].DocCount != 3 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 4, agg.Buckets[0].DocCount)\n\t}\n\n\tif agg.Buckets[1].From == nil {\n\t\tt.Errorf(\"expected From != %v; got: %v\", nil, agg.Buckets[1].From)\n\t}\n\tif *agg.Buckets[1].From != float64(100.0) {\n\t\tt.Errorf(\"expected From = %v; got: %v\", float64(100.0), *agg.Buckets[1].From)\n\t}\n\tif agg.Buckets[1].To == nil {\n\t\tt.Errorf(\"expected To != %v; got: %v\", nil, agg.Buckets[1].To)\n\t}\n\tif *agg.Buckets[1].To != float64(300.0) {\n\t\tt.Errorf(\"expected From = %v; got: %v\", float64(300.0), *agg.Buckets[1].To)\n\t}\n\tif agg.Buckets[1].DocCount != 1 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 1, agg.Buckets[1].DocCount)\n\t}\n\n\tif agg.Buckets[2].From == nil {\n\t\tt.Errorf(\"expected From != %v; got: %v\", nil, agg.Buckets[2].From)\n\t}\n\tif *agg.Buckets[2].From != float64(300.0) {\n\t\tt.Errorf(\"expected From = %v; got: %v\", float64(300.0), *agg.Buckets[2].From)\n\t}\n\tif agg.Buckets[2].To != nil {\n\t\tt.Errorf(\"expected To = %v; got: %v\", nil, agg.Buckets[2].To)\n\t}\n\tif agg.Buckets[2].DocCount != 7 {\n\t\tt.Errorf(\"expected DocCount = %d; got: %d\", 7, agg.Buckets[2].DocCount)\n\t}\n}\n\nfunc TestAggsSubAggregates(t *testing.T) {\n\trs := `{\n\t\"users\" : {\n\t  \"doc_count_error_upper_bound\" : 1,\n\t  \"sum_other_doc_count\" : 2,\n\t  \"buckets\" : [ {\n\t    \"key\" : \"olivere\",\n\t    \"doc_count\" : 2,\n\t    \"ts\" : {\n\t      \"buckets\" : [ {\n\t        \"key_as_string\" : \"2012-01-01T00:00:00.000Z\",\n\t        \"key\" : 1325376000000,\n\t        \"doc_count\" : 2\n\t      } ]\n\t    }\n\t  }, {\n\t    \"key\" : \"sandrae\",\n\t    \"doc_count\" : 1,\n\t    \"ts\" : {\n\t      \"buckets\" : [ {\n\t        \"key_as_string\" : \"2011-01-01T00:00:00.000Z\",\n\t        \"key\" : 1293840000000,\n\t        \"doc_count\" : 1\n\t      } ]\n\t    }\n\t  } ]\n\t}\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(rs), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\t// Access top-level aggregation\n\tusers, found := aggs.Terms(\"users\")\n\tif !found {\n\t\tt.Fatalf(\"expected users aggregation to be found; got: %v\", found)\n\t}\n\tif users == nil {\n\t\tt.Fatalf(\"expected users aggregation; got: %v\", users)\n\t}\n\tif users.Buckets == nil {\n\t\tt.Fatalf(\"expected users buckets; got: %v\", users.Buckets)\n\t}\n\tif len(users.Buckets) != 2 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 2, len(users.Buckets))\n\t}\n\tif users.Buckets[0].Key != \"olivere\" {\n\t\tt.Errorf(\"expected key %q; got: %q\", \"olivere\", users.Buckets[0].Key)\n\t}\n\tif users.Buckets[0].DocCount != 2 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 2, users.Buckets[0].DocCount)\n\t}\n\tif users.Buckets[1].Key != \"sandrae\" {\n\t\tt.Errorf(\"expected key %q; got: %q\", \"sandrae\", users.Buckets[1].Key)\n\t}\n\tif users.Buckets[1].DocCount != 1 {\n\t\tt.Errorf(\"expected doc count %d; got: %d\", 1, users.Buckets[1].DocCount)\n\t}\n\n\t// Access sub-aggregation\n\tts, found := users.Buckets[0].DateHistogram(\"ts\")\n\tif !found {\n\t\tt.Fatalf(\"expected ts aggregation to be found; got: %v\", found)\n\t}\n\tif ts == nil {\n\t\tt.Fatalf(\"expected ts aggregation; got: %v\", ts)\n\t}\n\tif ts.Buckets == nil {\n\t\tt.Fatalf(\"expected ts buckets; got: %v\", ts.Buckets)\n\t}\n\tif len(ts.Buckets) != 1 {\n\t\tt.Errorf(\"expected %d bucket entries; got: %d\", 1, len(ts.Buckets))\n\t}\n\tif ts.Buckets[0].Key != 1325376000000 {\n\t\tt.Errorf(\"expected key %v; got: %v\", 1325376000000, ts.Buckets[0].Key)\n\t}\n\tif ts.Buckets[0].KeyAsString == nil {\n\t\tt.Fatalf(\"expected key_as_string != %v; got: %v\", nil, ts.Buckets[0].KeyAsString)\n\t}\n\tif *ts.Buckets[0].KeyAsString != \"2012-01-01T00:00:00.000Z\" {\n\t\tt.Errorf(\"expected key_as_string %q; got: %q\", \"2012-01-01T00:00:00.000Z\", *ts.Buckets[0].KeyAsString)\n\t}\n}\n\nfunc TestAggsPipelineAvgBucket(t *testing.T) {\n\ts := `{\n\t\"avg_monthly_sales\" : {\n\t  \"value\" : 328.33333333333333\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.AvgBucket(\"avg_monthly_sales\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(328.33333333333333) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(328.33333333333333), *agg.Value)\n\t}\n}\n\nfunc TestAggsPipelineSumBucket(t *testing.T) {\n\ts := `{\n\t\"sum_monthly_sales\" : {\n\t  \"value\" : 985\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.SumBucket(\"sum_monthly_sales\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(985) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(985), *agg.Value)\n\t}\n}\n\nfunc TestAggsPipelineMaxBucket(t *testing.T) {\n\ts := `{\n\t\"max_monthly_sales\" : {\n\t\t\"keys\": [\"2015/01/01 00:00:00\"],\n\t  \"value\" : 550\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.MaxBucket(\"max_monthly_sales\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif len(agg.Keys) != 1 {\n\t\tt.Fatalf(\"expected 1 key; got: %d\", len(agg.Keys))\n\t}\n\tif got, want := agg.Keys[0], \"2015/01/01 00:00:00\"; got != want {\n\t\tt.Fatalf(\"expected key %q; got: %v (%T)\", want, got, got)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(550) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(550), *agg.Value)\n\t}\n}\n\nfunc TestAggsPipelineMinBucket(t *testing.T) {\n\ts := `{\n\t\"min_monthly_sales\" : {\n\t\t\"keys\": [\"2015/02/01 00:00:00\"],\n\t  \"value\" : 60\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.MinBucket(\"min_monthly_sales\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif len(agg.Keys) != 1 {\n\t\tt.Fatalf(\"expected 1 key; got: %d\", len(agg.Keys))\n\t}\n\tif got, want := agg.Keys[0], \"2015/02/01 00:00:00\"; got != want {\n\t\tt.Fatalf(\"expected key %q; got: %v (%T)\", want, got, got)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(60) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(60), *agg.Value)\n\t}\n}\n\nfunc TestAggsPipelineMovAvg(t *testing.T) {\n\ts := `{\n\t\"the_movavg\" : {\n\t  \"value\" : 12.0\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.MovAvg(\"the_movavg\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(12.0) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(12.0), *agg.Value)\n\t}\n}\n\nfunc TestAggsPipelineDerivative(t *testing.T) {\n\ts := `{\n\t\"sales_deriv\" : {\n\t  \"value\" : 315\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Derivative(\"sales_deriv\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(315) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(315), *agg.Value)\n\t}\n}\n\nfunc TestAggsPipelinePercentilesBucket(t *testing.T) {\n\ts := `{\n\t\"sales_percentiles\": {\n\t  \"values\": {\n        \"25.0\": 100,\n        \"50.0\": 200,\n        \"75.0\": 300\n      }\n    }\n}`\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.PercentilesBucket(\"sales_percentiles\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif len(agg.Values) != 3 {\n\t\tt.Fatalf(\"expected aggregation map with three entries; got: %v\", agg.Values)\n\t}\n}\n\nfunc TestAggsPipelineStatsBucket(t *testing.T) {\n\ts := `{\n\t\"stats_monthly_sales\": {\n\t \"count\": 3,\n\t \"min\": 60.0,\n\t \"max\": 550.0,\n\t \"avg\": 328.3333333333333,\n\t \"sum\": 985.0\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.StatsBucket(\"stats_monthly_sales\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Count != 3 {\n\t\tt.Fatalf(\"expected aggregation count = %v; got: %v\", 3, agg.Count)\n\t}\n\tif agg.Min == nil {\n\t\tt.Fatalf(\"expected aggregation min != nil; got: %v\", agg.Min)\n\t}\n\tif *agg.Min != float64(60.0) {\n\t\tt.Fatalf(\"expected aggregation min = %v; got: %v\", float64(60.0), *agg.Min)\n\t}\n\tif agg.Max == nil {\n\t\tt.Fatalf(\"expected aggregation max != nil; got: %v\", agg.Max)\n\t}\n\tif *agg.Max != float64(550.0) {\n\t\tt.Fatalf(\"expected aggregation max = %v; got: %v\", float64(550.0), *agg.Max)\n\t}\n\tif agg.Avg == nil {\n\t\tt.Fatalf(\"expected aggregation avg != nil; got: %v\", agg.Avg)\n\t}\n\tif *agg.Avg != float64(328.3333333333333) {\n\t\tt.Fatalf(\"expected aggregation average = %v; got: %v\", float64(328.3333333333333), *agg.Avg)\n\t}\n\tif agg.Sum == nil {\n\t\tt.Fatalf(\"expected aggregation sum != nil; got: %v\", agg.Sum)\n\t}\n\tif *agg.Sum != float64(985.0) {\n\t\tt.Fatalf(\"expected aggregation sum = %v; got: %v\", float64(985.0), *agg.Sum)\n\t}\n}\n\nfunc TestAggsPipelineCumulativeSum(t *testing.T) {\n\ts := `{\n\t\"cumulative_sales\" : {\n\t  \"value\" : 550\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.CumulativeSum(\"cumulative_sales\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(550) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(550), *agg.Value)\n\t}\n}\n\nfunc TestAggsPipelineBucketScript(t *testing.T) {\n\ts := `{\n\t\"t-shirt-percentage\" : {\n\t  \"value\" : 20\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.BucketScript(\"t-shirt-percentage\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(20) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(20), *agg.Value)\n\t}\n}\n\nfunc TestAggsPipelineSerialDiff(t *testing.T) {\n\ts := `{\n\t\"the_diff\" : {\n\t  \"value\" : -722.0\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.SerialDiff(\"the_diff\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif agg.Value == nil {\n\t\tt.Fatalf(\"expected aggregation value != nil; got: %v\", agg.Value)\n\t}\n\tif *agg.Value != float64(-722.0) {\n\t\tt.Fatalf(\"expected aggregation value = %v; got: %v\", float64(20), *agg.Value)\n\t}\n}\n\nfunc TestAggsComposite(t *testing.T) {\n\ts := `{\n\t\"the_composite\" : {\n\t\t\"buckets\" : [\n\t\t  {\n\t\t\t\"key\" : {\n\t\t\t  \"composite_users\" : \"olivere\",\n\t\t\t  \"composite_retweets\" : 0.0,\n\t\t\t  \"composite_created\" : 1349856720000\n\t\t\t},\n\t\t\t\"doc_count\" : 1\n\t\t  },\n\t\t  {\n\t\t\t\"key\" : {\n\t\t\t  \"composite_users\" : \"olivere\",\n\t\t\t  \"composite_retweets\" : 108.0,\n\t\t\t  \"composite_created\" : 1355333880000\n\t\t\t},\n\t\t\t\"doc_count\" : 1\n\t\t  },\n\t\t  {\n\t\t\t\"key\" : {\n\t\t\t  \"composite_users\" : \"sandrae\",\n\t\t\t  \"composite_retweets\" : 12.0,\n\t\t\t  \"composite_created\" : 1321009080000\n\t\t\t},\n\t\t\t\"doc_count\" : 1\n\t\t  }\n\t\t]\n\t  }\n\t}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %v\", err)\n\t}\n\n\tagg, found := aggs.Composite(\"the_composite\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %v\", agg)\n\t}\n\tif want, have := 3, len(agg.Buckets); want != have {\n\t\tt.Fatalf(\"expected aggregation buckets length = %v; got: %v\", want, have)\n\t}\n\n\t// 1st bucket\n\tbucket := agg.Buckets[0]\n\tif want, have := int64(1), bucket.DocCount; want != have {\n\t\tt.Fatalf(\"expected aggregation bucket doc count = %v; got: %v\", want, have)\n\t}\n\tif want, have := 3, len(bucket.Key); want != have {\n\t\tt.Fatalf(\"expected aggregation bucket key length = %v; got: %v\", want, have)\n\t}\n\tv, found := bucket.Key[\"composite_users\"]\n\tif !found {\n\t\tt.Fatalf(\"expected to find bucket key %q\", \"composite_users\")\n\t}\n\ts, ok := v.(string)\n\tif !ok {\n\t\tt.Fatalf(\"expected to have bucket key of type string; got: %T\", v)\n\t}\n\tif want, have := \"olivere\", s; want != have {\n\t\tt.Fatalf(\"expected to find bucket key value %q; got: %q\", want, have)\n\t}\n\tv, found = bucket.Key[\"composite_retweets\"]\n\tif !found {\n\t\tt.Fatalf(\"expected to find bucket key %q\", \"composite_retweets\")\n\t}\n\tf, ok := v.(float64)\n\tif !ok {\n\t\tt.Fatalf(\"expected to have bucket key of type string; got: %T\", v)\n\t}\n\tif want, have := 0.0, f; want != have {\n\t\tt.Fatalf(\"expected to find bucket key value %v; got: %v\", want, have)\n\t}\n\tv, found = bucket.Key[\"composite_created\"]\n\tif !found {\n\t\tt.Fatalf(\"expected to find bucket key %q\", \"composite_created\")\n\t}\n\tf, ok = v.(float64)\n\tif !ok {\n\t\tt.Fatalf(\"expected to have bucket key of type string; got: %T\", v)\n\t}\n\tif want, have := 1349856720000.0, f; want != have {\n\t\tt.Fatalf(\"expected to find bucket key value %v; got: %v\", want, have)\n\t}\n\n\t// 2nd bucket\n\tbucket = agg.Buckets[1]\n\tif want, have := int64(1), bucket.DocCount; want != have {\n\t\tt.Fatalf(\"expected aggregation bucket doc count = %v; got: %v\", want, have)\n\t}\n\tif want, have := 3, len(bucket.Key); want != have {\n\t\tt.Fatalf(\"expected aggregation bucket key length = %v; got: %v\", want, have)\n\t}\n\tv, found = bucket.Key[\"composite_users\"]\n\tif !found {\n\t\tt.Fatalf(\"expected to find bucket key %q\", \"composite_users\")\n\t}\n\ts, ok = v.(string)\n\tif !ok {\n\t\tt.Fatalf(\"expected to have bucket key of type string; got: %T\", v)\n\t}\n\tif want, have := \"olivere\", s; want != have {\n\t\tt.Fatalf(\"expected to find bucket key value %q; got: %q\", want, have)\n\t}\n\tv, found = bucket.Key[\"composite_retweets\"]\n\tif !found {\n\t\tt.Fatalf(\"expected to find bucket key %q\", \"composite_retweets\")\n\t}\n\tf, ok = v.(float64)\n\tif !ok {\n\t\tt.Fatalf(\"expected to have bucket key of type string; got: %T\", v)\n\t}\n\tif want, have := 108.0, f; want != have {\n\t\tt.Fatalf(\"expected to find bucket key value %v; got: %v\", want, have)\n\t}\n\tv, found = bucket.Key[\"composite_created\"]\n\tif !found {\n\t\tt.Fatalf(\"expected to find bucket key %q\", \"composite_created\")\n\t}\n\tf, ok = v.(float64)\n\tif !ok {\n\t\tt.Fatalf(\"expected to have bucket key of type string; got: %T\", v)\n\t}\n\tif want, have := 1355333880000.0, f; want != have {\n\t\tt.Fatalf(\"expected to find bucket key value %v; got: %v\", want, have)\n\t}\n\n\t// 3rd bucket\n\tbucket = agg.Buckets[2]\n\tif want, have := int64(1), bucket.DocCount; want != have {\n\t\tt.Fatalf(\"expected aggregation bucket doc count = %v; got: %v\", want, have)\n\t}\n\tif want, have := 3, len(bucket.Key); want != have {\n\t\tt.Fatalf(\"expected aggregation bucket key length = %v; got: %v\", want, have)\n\t}\n\tv, found = bucket.Key[\"composite_users\"]\n\tif !found {\n\t\tt.Fatalf(\"expected to find bucket key %q\", \"composite_users\")\n\t}\n\ts, ok = v.(string)\n\tif !ok {\n\t\tt.Fatalf(\"expected to have bucket key of type string; got: %T\", v)\n\t}\n\tif want, have := \"sandrae\", s; want != have {\n\t\tt.Fatalf(\"expected to find bucket key value %q; got: %q\", want, have)\n\t}\n\tv, found = bucket.Key[\"composite_retweets\"]\n\tif !found {\n\t\tt.Fatalf(\"expected to find bucket key %q\", \"composite_retweets\")\n\t}\n\tf, ok = v.(float64)\n\tif !ok {\n\t\tt.Fatalf(\"expected to have bucket key of type string; got: %T\", v)\n\t}\n\tif want, have := 12.0, f; want != have {\n\t\tt.Fatalf(\"expected to find bucket key value %v; got: %v\", want, have)\n\t}\n\tv, found = bucket.Key[\"composite_created\"]\n\tif !found {\n\t\tt.Fatalf(\"expected to find bucket key %q\", \"composite_created\")\n\t}\n\tf, ok = v.(float64)\n\tif !ok {\n\t\tt.Fatalf(\"expected to have bucket key of type string; got: %T\", v)\n\t}\n\tif want, have := 1321009080000.0, f; want != have {\n\t\tt.Fatalf(\"expected to find bucket key value %v; got: %v\", want, have)\n\t}\n}\n\nfunc TestAggsScriptedMetric(t *testing.T) {\n\ts := `{\n  \"bool_metric\": {\n    \"value\": true\n  },\n  \"int_metric\": {\n    \"value\": 1\n  },\n  \"float_metric\": {\n    \"value\": 2.5\n  },\n  \"string_metric\": {\n    \"value\": \"test\"\n  },\n  \"slice_metric\": {\n    \"value\": [\n      1,\n      2,\n      3\n    ]\n  },\n  \"map_metric\": {\n    \"value\": {\n      \"a\": \"1\",\n      \"b\": \"2\"\n    }\n  }\n}`\n\n\taggs := new(Aggregations)\n\terr := json.Unmarshal([]byte(s), &aggs)\n\tif err != nil {\n\t\tt.Fatalf(\"expected no error decoding; got: %+v\", err)\n\t}\n\n\tagg, found := aggs.ScriptedMetric(\"bool_metric\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %+v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %+v\", agg)\n\t}\n\tif v, ok := agg.Value.(bool); !ok || !v {\n\t\tt.Fatalf(\"expected aggregation value is bool true; got: %+v\", agg.Value)\n\t}\n\n\tagg, found = aggs.ScriptedMetric(\"int_metric\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %+v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %+v\", agg)\n\t}\n\tif v, ok := agg.Value.(json.Number); ok {\n\t\tif iv, err := v.Int64(); err != nil || iv != 1 {\n\t\t\tt.Fatalf(\"expected aggregation value is 1; got: %+v\", iv)\n\t\t}\n\t} else {\n\t\tt.Fatalf(\"expected aggregation value is json.Number; got: %+v\", agg.Value)\n\t}\n\n\tagg, found = aggs.ScriptedMetric(\"float_metric\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %+v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %+v\", agg)\n\t}\n\tif v, ok := agg.Value.(json.Number); ok {\n\t\tif iv, err := v.Float64(); err != nil || iv != 2.5 {\n\t\t\tt.Fatalf(\"expected aggregation value is 2.5; got: %+v\", iv)\n\t\t}\n\t} else {\n\t\tt.Fatalf(\"expected aggregation value is json.Number; got: %+v\", agg.Value)\n\t}\n\n\tagg, found = aggs.ScriptedMetric(\"string_metric\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %+v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %+v\", agg)\n\t}\n\tif v, ok := agg.Value.(string); !ok || v != \"test\" {\n\t\tt.Fatalf(\"expected aggregation value is test; got: %+v\", agg.Value)\n\t}\n\n\tagg, found = aggs.ScriptedMetric(\"slice_metric\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %+v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %+v\", agg)\n\t}\n\tif v, ok := agg.Value.([]interface{}); ok {\n\t\texpected := []interface{}{json.Number(\"1\"), json.Number(\"2\"), json.Number(\"3\")}\n\t\tif !reflect.DeepEqual(v, expected) {\n\t\t\tt.Fatalf(\"expected %+v; got: %+v\", expected, v)\n\t\t}\n\t} else {\n\t\tt.Fatalf(\"expected aggregation value is []interface{}; got: %+v\", agg.Value)\n\t}\n\n\tagg, found = aggs.ScriptedMetric(\"map_metric\")\n\tif !found {\n\t\tt.Fatalf(\"expected aggregation to be found; got: %+v\", found)\n\t}\n\tif agg == nil {\n\t\tt.Fatalf(\"expected aggregation != nil; got: %+v\", agg)\n\t}\n\tif v, ok := agg.Value.(map[string]interface{}); ok {\n\t\texpected := map[string]interface{}{\n\t\t\t\"a\": \"1\",\n\t\t\t\"b\": \"2\",\n\t\t}\n\t\tif !reflect.DeepEqual(v, expected) {\n\t\t\tt.Fatalf(\"expected %+v; got: %+v\", expected, v)\n\t\t}\n\t} else {\n\t\tt.Fatalf(\"expected aggregation value is map[string]interface{}; got: %+v\", agg.Value)\n\t}\n}\n"
  },
  {
    "path": "search_collapse_builder.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// CollapseBuilder enables field collapsing on a search request.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-collapse.html\n// for details.\ntype CollapseBuilder struct {\n\tfield                      string\n\tinnerHits                  []*InnerHit\n\tmaxConcurrentGroupRequests *int\n}\n\n// NewCollapseBuilder creates a new CollapseBuilder.\nfunc NewCollapseBuilder(field string) *CollapseBuilder {\n\treturn &CollapseBuilder{field: field}\n}\n\n// Field to collapse.\nfunc (b *CollapseBuilder) Field(field string) *CollapseBuilder {\n\tb.field = field\n\treturn b\n}\n\n// InnerHit option to expand the collapsed results.\nfunc (b *CollapseBuilder) InnerHit(innerHits ...*InnerHit) *CollapseBuilder {\n\tb.innerHits = append(b.innerHits, innerHits...)\n\treturn b\n}\n\n// MaxConcurrentGroupRequests is the maximum number of group requests that are\n// allowed to be ran concurrently in the inner_hits phase.\nfunc (b *CollapseBuilder) MaxConcurrentGroupRequests(max int) *CollapseBuilder {\n\tb.maxConcurrentGroupRequests = &max\n\treturn b\n}\n\n// Source generates the JSON serializable fragment for the CollapseBuilder.\nfunc (b *CollapseBuilder) Source() (interface{}, error) {\n\t// {\n\t//   \"field\": \"user\",\n\t//   \"inner_hits\": [{\n\t//     \"name\": \"last_tweets\",\n\t//     \"size\": 5,\n\t//     \"sort\": [{ \"date\": \"asc\" }]\n\t//   }],\n\t//   \"max_concurrent_group_searches\": 4\n\t// }\n\tsrc := map[string]interface{}{\n\t\t\"field\": b.field,\n\t}\n\n\tif len(b.innerHits) > 0 {\n\t\tvar innerHits []interface{}\n\t\tfor _, h := range b.innerHits {\n\t\t\thits, err := h.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tinnerHits = append(innerHits, hits)\n\t\t}\n\t\tsrc[\"inner_hits\"] = innerHits\n\t}\n\n\tif b.maxConcurrentGroupRequests != nil {\n\t\tsrc[\"max_concurrent_group_searches\"] = *b.maxConcurrentGroupRequests\n\t}\n\n\treturn src, nil\n}\n"
  },
  {
    "path": "search_collapse_builder_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestCollapseBuilderSource(t *testing.T) {\n\tb := NewCollapseBuilder(\"user\").\n\t\tInnerHit(NewInnerHit().Name(\"last_tweets\").Size(5).Sort(\"date\", true)).\n\t\tMaxConcurrentGroupRequests(4)\n\tsrc, err := b.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"field\":\"user\",\"inner_hits\":[{\"name\":\"last_tweets\",\"size\":5,\"sort\":[{\"date\":{\"order\":\"asc\"}}]}],\"max_concurrent_group_searches\":4}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCollapseBuilderSourceMultipleInnerHits(t *testing.T) {\n\tb := NewCollapseBuilder(\"user.id\").\n\t\tInnerHit(NewInnerHit().Name(\"largest_responses\").Size(3).Sort(\"http.response.bytes\", false)).\n\t\tInnerHit(NewInnerHit().Name(\"most_recent\").Size(4).Sort(\"@timestamp\", false)).\n\t\tMaxConcurrentGroupRequests(5)\n\tsrc, err := b.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"field\":\"user.id\",\"inner_hits\":[{\"name\":\"largest_responses\",\"size\":3,\"sort\":[{\"http.response.bytes\":{\"order\":\"desc\"}}]},{\"name\":\"most_recent\",\"size\":4,\"sort\":[{\"@timestamp\":{\"order\":\"desc\"}}]}],\"max_concurrent_group_searches\":5}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_bool.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"fmt\"\n\n// A bool query matches documents matching boolean\n// combinations of other queries.\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-bool-query.html\ntype BoolQuery struct {\n\tQuery\n\tmustClauses        []Query\n\tmustNotClauses     []Query\n\tfilterClauses      []Query\n\tshouldClauses      []Query\n\tboost              *float64\n\tminimumShouldMatch string\n\tadjustPureNegative *bool\n\tqueryName          string\n}\n\n// Creates a new bool query.\nfunc NewBoolQuery() *BoolQuery {\n\treturn &BoolQuery{\n\t\tmustClauses:    make([]Query, 0),\n\t\tmustNotClauses: make([]Query, 0),\n\t\tfilterClauses:  make([]Query, 0),\n\t\tshouldClauses:  make([]Query, 0),\n\t}\n}\n\nfunc (q *BoolQuery) Must(queries ...Query) *BoolQuery {\n\tq.mustClauses = append(q.mustClauses, queries...)\n\treturn q\n}\n\nfunc (q *BoolQuery) MustNot(queries ...Query) *BoolQuery {\n\tq.mustNotClauses = append(q.mustNotClauses, queries...)\n\treturn q\n}\n\nfunc (q *BoolQuery) Filter(filters ...Query) *BoolQuery {\n\tq.filterClauses = append(q.filterClauses, filters...)\n\treturn q\n}\n\nfunc (q *BoolQuery) Should(queries ...Query) *BoolQuery {\n\tq.shouldClauses = append(q.shouldClauses, queries...)\n\treturn q\n}\n\nfunc (q *BoolQuery) Boost(boost float64) *BoolQuery {\n\tq.boost = &boost\n\treturn q\n}\n\nfunc (q *BoolQuery) MinimumShouldMatch(minimumShouldMatch string) *BoolQuery {\n\tq.minimumShouldMatch = minimumShouldMatch\n\treturn q\n}\n\nfunc (q *BoolQuery) MinimumNumberShouldMatch(minimumNumberShouldMatch int) *BoolQuery {\n\tq.minimumShouldMatch = fmt.Sprintf(\"%d\", minimumNumberShouldMatch)\n\treturn q\n}\n\nfunc (q *BoolQuery) AdjustPureNegative(adjustPureNegative bool) *BoolQuery {\n\tq.adjustPureNegative = &adjustPureNegative\n\treturn q\n}\n\nfunc (q *BoolQuery) QueryName(queryName string) *BoolQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Creates the query source for the bool query.\nfunc (q *BoolQuery) Source() (interface{}, error) {\n\t// {\n\t//\t\"bool\" : {\n\t//\t\t\"must\" : {\n\t//\t\t\t\"term\" : { \"user\" : \"kimchy\" }\n\t//\t\t},\n\t//\t\t\"must_not\" : {\n\t//\t\t\t\"range\" : {\n\t//\t\t\t\t\"age\" : { \"from\" : 10, \"to\" : 20 }\n\t//\t\t\t}\n\t//\t\t},\n\t//    \"filter\" : [\n\t//      ...\n\t//    ]\n\t//\t\t\"should\" : [\n\t//\t\t\t{\n\t//\t\t\t\t\"term\" : { \"tag\" : \"wow\" }\n\t//\t\t\t},\n\t//\t\t\t{\n\t//\t\t\t\t\"term\" : { \"tag\" : \"elasticsearch\" }\n\t//\t\t\t}\n\t//\t\t],\n\t//\t\t\"minimum_should_match\" : 1,\n\t//\t\t\"boost\" : 1.0\n\t//\t}\n\t// }\n\n\tquery := make(map[string]interface{})\n\n\tboolClause := make(map[string]interface{})\n\tquery[\"bool\"] = boolClause\n\n\t// must\n\tif len(q.mustClauses) == 1 {\n\t\tsrc, err := q.mustClauses[0].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tboolClause[\"must\"] = src\n\t} else if len(q.mustClauses) > 1 {\n\t\tvar clauses []interface{}\n\t\tfor _, subQuery := range q.mustClauses {\n\t\t\tsrc, err := subQuery.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tclauses = append(clauses, src)\n\t\t}\n\t\tboolClause[\"must\"] = clauses\n\t}\n\n\t// must_not\n\tif len(q.mustNotClauses) == 1 {\n\t\tsrc, err := q.mustNotClauses[0].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tboolClause[\"must_not\"] = src\n\t} else if len(q.mustNotClauses) > 1 {\n\t\tvar clauses []interface{}\n\t\tfor _, subQuery := range q.mustNotClauses {\n\t\t\tsrc, err := subQuery.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tclauses = append(clauses, src)\n\t\t}\n\t\tboolClause[\"must_not\"] = clauses\n\t}\n\n\t// filter\n\tif len(q.filterClauses) == 1 {\n\t\tsrc, err := q.filterClauses[0].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tboolClause[\"filter\"] = src\n\t} else if len(q.filterClauses) > 1 {\n\t\tvar clauses []interface{}\n\t\tfor _, subQuery := range q.filterClauses {\n\t\t\tsrc, err := subQuery.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tclauses = append(clauses, src)\n\t\t}\n\t\tboolClause[\"filter\"] = clauses\n\t}\n\n\t// should\n\tif len(q.shouldClauses) == 1 {\n\t\tsrc, err := q.shouldClauses[0].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tboolClause[\"should\"] = src\n\t} else if len(q.shouldClauses) > 1 {\n\t\tvar clauses []interface{}\n\t\tfor _, subQuery := range q.shouldClauses {\n\t\t\tsrc, err := subQuery.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tclauses = append(clauses, src)\n\t\t}\n\t\tboolClause[\"should\"] = clauses\n\t}\n\n\tif q.boost != nil {\n\t\tboolClause[\"boost\"] = *q.boost\n\t}\n\tif q.minimumShouldMatch != \"\" {\n\t\tboolClause[\"minimum_should_match\"] = q.minimumShouldMatch\n\t}\n\tif q.adjustPureNegative != nil {\n\t\tboolClause[\"adjust_pure_negative\"] = *q.adjustPureNegative\n\t}\n\tif q.queryName != \"\" {\n\t\tboolClause[\"_name\"] = q.queryName\n\t}\n\n\treturn query, nil\n}\n"
  },
  {
    "path": "search_queries_bool_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestBoolQuery(t *testing.T) {\n\tq := NewBoolQuery()\n\tq = q.Must(NewTermQuery(\"tag\", \"wow\"))\n\tq = q.MustNot(NewRangeQuery(\"age\").From(10).To(20))\n\tq = q.Filter(NewTermQuery(\"account\", \"1\"))\n\tq = q.Should(NewTermQuery(\"tag\", \"sometag\"), NewTermQuery(\"tag\", \"sometagtag\"))\n\tq = q.Boost(10)\n\tq = q.QueryName(\"Test\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"bool\":{\"_name\":\"Test\",\"boost\":10,\"filter\":{\"term\":{\"account\":\"1\"}},\"must\":{\"term\":{\"tag\":\"wow\"}},\"must_not\":{\"range\":{\"age\":{\"from\":10,\"include_lower\":true,\"include_upper\":true,\"to\":20}}},\"should\":[{\"term\":{\"tag\":\"sometag\"}},{\"term\":{\"tag\":\"sometagtag\"}}]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_boosting.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// A boosting query can be used to effectively\n// demote results that match a given query.\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-boosting-query.html\ntype BoostingQuery struct {\n\tQuery\n\tpositiveClause Query\n\tnegativeClause Query\n\tnegativeBoost  *float64\n\tboost          *float64\n}\n\n// Creates a new boosting query.\nfunc NewBoostingQuery() *BoostingQuery {\n\treturn &BoostingQuery{}\n}\n\nfunc (q *BoostingQuery) Positive(positive Query) *BoostingQuery {\n\tq.positiveClause = positive\n\treturn q\n}\n\nfunc (q *BoostingQuery) Negative(negative Query) *BoostingQuery {\n\tq.negativeClause = negative\n\treturn q\n}\n\nfunc (q *BoostingQuery) NegativeBoost(negativeBoost float64) *BoostingQuery {\n\tq.negativeBoost = &negativeBoost\n\treturn q\n}\n\nfunc (q *BoostingQuery) Boost(boost float64) *BoostingQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// Creates the query source for the boosting query.\nfunc (q *BoostingQuery) Source() (interface{}, error) {\n\t// {\n\t//     \"boosting\" : {\n\t//         \"positive\" : {\n\t//             \"term\" : {\n\t//                 \"field1\" : \"value1\"\n\t//             }\n\t//         },\n\t//         \"negative\" : {\n\t//             \"term\" : {\n\t//                 \"field2\" : \"value2\"\n\t//             }\n\t//         },\n\t//         \"negative_boost\" : 0.2\n\t//     }\n\t// }\n\n\tquery := make(map[string]interface{})\n\n\tboostingClause := make(map[string]interface{})\n\tquery[\"boosting\"] = boostingClause\n\n\t// Negative and positive clause as well as negative boost\n\t// are mandatory in the Java client.\n\n\t// positive\n\tif q.positiveClause != nil {\n\t\tsrc, err := q.positiveClause.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tboostingClause[\"positive\"] = src\n\t}\n\n\t// negative\n\tif q.negativeClause != nil {\n\t\tsrc, err := q.negativeClause.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tboostingClause[\"negative\"] = src\n\t}\n\n\tif q.negativeBoost != nil {\n\t\tboostingClause[\"negative_boost\"] = *q.negativeBoost\n\t}\n\n\tif q.boost != nil {\n\t\tboostingClause[\"boost\"] = *q.boost\n\t}\n\n\treturn query, nil\n}\n"
  },
  {
    "path": "search_queries_boosting_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestBoostingQuery(t *testing.T) {\n\tq := NewBoostingQuery()\n\tq = q.Positive(NewTermQuery(\"tag\", \"wow\"))\n\tq = q.Negative(NewRangeQuery(\"age\").From(10).To(20))\n\tq = q.NegativeBoost(0.2)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"boosting\":{\"negative\":{\"range\":{\"age\":{\"from\":10,\"include_lower\":true,\"include_upper\":true,\"to\":20}}},\"negative_boost\":0.2,\"positive\":{\"term\":{\"tag\":\"wow\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_combined_fields.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"fmt\"\n\n// CombinedFieldsQuery supports searching multiple text fields as if their\n// contents had been indexed into one combined field.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.13/query-dsl-combined-fields-query.html\ntype CombinedFieldsQuery struct {\n\ttext                            interface{}\n\tfields                          []string\n\tfieldBoosts                     map[string]*float64\n\tautoGenerateSynonymsPhraseQuery *bool\n\toperator                        string // AND or OR\n\tminimumShouldMatch              string\n\tzeroTermsQuery                  string\n}\n\n// NewCombinedFieldsQuery creates and initializes a new CombinedFieldsQuery.\nfunc NewCombinedFieldsQuery(text interface{}, fields ...string) *CombinedFieldsQuery {\n\tq := &CombinedFieldsQuery{\n\t\ttext:        text,\n\t\tfieldBoosts: make(map[string]*float64),\n\t}\n\tq.fields = append(q.fields, fields...)\n\treturn q\n}\n\n// Field adds a field to run the multi match against.\nfunc (q *CombinedFieldsQuery) Field(field string) *CombinedFieldsQuery {\n\tq.fields = append(q.fields, field)\n\treturn q\n}\n\n// FieldWithBoost adds a field to run the multi match against with a specific boost.\nfunc (q *CombinedFieldsQuery) FieldWithBoost(field string, boost float64) *CombinedFieldsQuery {\n\tq.fields = append(q.fields, field)\n\tq.fieldBoosts[field] = &boost\n\treturn q\n}\n\n// AutoGenerateSynonymsPhraseQuery indicates whether phrase queries should be\n// automatically generated for multi terms synonyms. Defaults to true.\nfunc (q *CombinedFieldsQuery) AutoGenerateSynonymsPhraseQuery(enable bool) *CombinedFieldsQuery {\n\tq.autoGenerateSynonymsPhraseQuery = &enable\n\treturn q\n}\n\n// Operator sets the operator to use when using boolean query.\n// It can be either AND or OR (default).\nfunc (q *CombinedFieldsQuery) Operator(operator string) *CombinedFieldsQuery {\n\tq.operator = operator\n\treturn q\n}\n\n// MinimumShouldMatch represents the minimum number of optional should clauses\n// to match.\nfunc (q *CombinedFieldsQuery) MinimumShouldMatch(minimumShouldMatch string) *CombinedFieldsQuery {\n\tq.minimumShouldMatch = minimumShouldMatch\n\treturn q\n}\n\n// ZeroTermsQuery can be \"all\" or \"none\".\nfunc (q *CombinedFieldsQuery) ZeroTermsQuery(zeroTermsQuery string) *CombinedFieldsQuery {\n\tq.zeroTermsQuery = zeroTermsQuery\n\treturn q\n}\n\n// Source returns JSON for the query.\nfunc (q *CombinedFieldsQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tcombinedFields := make(map[string]interface{})\n\tsource[\"combined_fields\"] = combinedFields\n\n\tcombinedFields[\"query\"] = q.text\n\n\tfields := []string{}\n\tfor _, field := range q.fields {\n\t\tif boost, found := q.fieldBoosts[field]; found {\n\t\t\tif boost != nil {\n\t\t\t\tfields = append(fields, fmt.Sprintf(\"%s^%f\", field, *boost))\n\t\t\t} else {\n\t\t\t\tfields = append(fields, field)\n\t\t\t}\n\t\t} else {\n\t\t\tfields = append(fields, field)\n\t\t}\n\t}\n\tcombinedFields[\"fields\"] = fields\n\n\tif q.autoGenerateSynonymsPhraseQuery != nil {\n\t\tcombinedFields[\"auto_generate_synonyms_phrase_query\"] = q.autoGenerateSynonymsPhraseQuery\n\t}\n\tif q.operator != \"\" {\n\t\tcombinedFields[\"operator\"] = q.operator\n\t}\n\tif q.minimumShouldMatch != \"\" {\n\t\tcombinedFields[\"minimum_should_match\"] = q.minimumShouldMatch\n\t}\n\tif q.zeroTermsQuery != \"\" {\n\t\tcombinedFields[\"zero_terms_query\"] = q.zeroTermsQuery\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_combined_fields_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestCombinedFieldsQuery(t *testing.T) {\n\tq := NewCombinedFieldsQuery(\"query text\", \"f1\", \"f2\").\n\t\tField(\"f3\").\n\t\tFieldWithBoost(\"f4\", 2.0).\n\t\tAutoGenerateSynonymsPhraseQuery(false).\n\t\tOperator(\"AND\").\n\t\tMinimumShouldMatch(\"3\").\n\t\tZeroTermsQuery(\"all\")\n\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"combined_fields\":{\"auto_generate_synonyms_phrase_query\":false,\"fields\":[\"f1\",\"f2\",\"f3\",\"f4^2.000000\"],\"minimum_should_match\":\"3\",\"operator\":\"AND\",\"query\":\"query text\",\"zero_terms_query\":\"all\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_common_terms.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// CommonTermsQuery is a modern alternative to stopwords\n// which improves the precision and recall of search results\n// (by taking stopwords into account), without sacrificing performance.\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-common-terms-query.html\n//\n// Deprecated: Use Match query instead (7.3.0+), which skips blocks of\n// documents efficiently, without any configuration, provided that the\n// total number of hits is not tracked.\ntype CommonTermsQuery struct {\n\tQuery\n\tname                       string\n\ttext                       interface{}\n\tcutoffFreq                 *float64\n\thighFreq                   *float64\n\thighFreqOp                 string\n\thighFreqMinimumShouldMatch string\n\tlowFreq                    *float64\n\tlowFreqOp                  string\n\tlowFreqMinimumShouldMatch  string\n\tanalyzer                   string\n\tboost                      *float64\n\tqueryName                  string\n}\n\n// NewCommonTermsQuery creates and initializes a new common terms query.\n//\n// Deprecated: Common Terms Query was deprecated in >= 7.3.0. See https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-common-terms-query.html.\nfunc NewCommonTermsQuery(name string, text interface{}) *CommonTermsQuery {\n\treturn &CommonTermsQuery{name: name, text: text}\n}\n\nfunc (q *CommonTermsQuery) CutoffFrequency(f float64) *CommonTermsQuery {\n\tq.cutoffFreq = &f\n\treturn q\n}\n\nfunc (q *CommonTermsQuery) HighFreq(f float64) *CommonTermsQuery {\n\tq.highFreq = &f\n\treturn q\n}\n\nfunc (q *CommonTermsQuery) HighFreqOperator(op string) *CommonTermsQuery {\n\tq.highFreqOp = op\n\treturn q\n}\n\nfunc (q *CommonTermsQuery) HighFreqMinimumShouldMatch(minShouldMatch string) *CommonTermsQuery {\n\tq.highFreqMinimumShouldMatch = minShouldMatch\n\treturn q\n}\n\nfunc (q *CommonTermsQuery) LowFreq(f float64) *CommonTermsQuery {\n\tq.lowFreq = &f\n\treturn q\n}\n\nfunc (q *CommonTermsQuery) LowFreqOperator(op string) *CommonTermsQuery {\n\tq.lowFreqOp = op\n\treturn q\n}\n\nfunc (q *CommonTermsQuery) LowFreqMinimumShouldMatch(minShouldMatch string) *CommonTermsQuery {\n\tq.lowFreqMinimumShouldMatch = minShouldMatch\n\treturn q\n}\n\nfunc (q *CommonTermsQuery) Analyzer(analyzer string) *CommonTermsQuery {\n\tq.analyzer = analyzer\n\treturn q\n}\n\nfunc (q *CommonTermsQuery) Boost(boost float64) *CommonTermsQuery {\n\tq.boost = &boost\n\treturn q\n}\n\nfunc (q *CommonTermsQuery) QueryName(queryName string) *CommonTermsQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Creates the query source for the common query.\nfunc (q *CommonTermsQuery) Source() (interface{}, error) {\n\t//  {\n\t//    \"common\": {\n\t//      \"body\": {\n\t//        \"query\":            \"this is bonsai cool\",\n\t//        \"cutoff_frequency\": 0.001\n\t//      }\n\t//    }\n\t//  }\n\tsource := make(map[string]interface{})\n\tbody := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\n\tsource[\"common\"] = body\n\tbody[q.name] = query\n\tquery[\"query\"] = q.text\n\n\tif q.cutoffFreq != nil {\n\t\tquery[\"cutoff_frequency\"] = *q.cutoffFreq\n\t}\n\tif q.highFreq != nil {\n\t\tquery[\"high_freq\"] = *q.highFreq\n\t}\n\tif q.highFreqOp != \"\" {\n\t\tquery[\"high_freq_operator\"] = q.highFreqOp\n\t}\n\tif q.lowFreq != nil {\n\t\tquery[\"low_freq\"] = *q.lowFreq\n\t}\n\tif q.lowFreqOp != \"\" {\n\t\tquery[\"low_freq_operator\"] = q.lowFreqOp\n\t}\n\tif q.lowFreqMinimumShouldMatch != \"\" || q.highFreqMinimumShouldMatch != \"\" {\n\t\tmm := make(map[string]interface{})\n\t\tif q.lowFreqMinimumShouldMatch != \"\" {\n\t\t\tmm[\"low_freq\"] = q.lowFreqMinimumShouldMatch\n\t\t}\n\t\tif q.highFreqMinimumShouldMatch != \"\" {\n\t\t\tmm[\"high_freq\"] = q.highFreqMinimumShouldMatch\n\t\t}\n\t\tquery[\"minimum_should_match\"] = mm\n\t}\n\tif q.analyzer != \"\" {\n\t\tquery[\"analyzer\"] = q.analyzer\n\t}\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_common_terms_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t_ \"net/http\"\n\t\"testing\"\n)\n\nfunc TestCommonTermsQuery(t *testing.T) {\n\tq := NewCommonTermsQuery(\"message\", \"Golang\").CutoffFrequency(0.001)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"common\":{\"message\":{\"cutoff_frequency\":0.001,\"query\":\"Golang\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchQueriesCommonTermsQuery(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// Deprecated in >= 7.3.0\n\t// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-common-terms-query.html\n\tesversion, err := client.ElasticsearchVersion(DefaultURL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif esversion < \"7.3.0\" {\n\t\tt.Skipf(\"Elasticsearch versions >= 7.3.0 deprecated Common Terms Query. \"+\n\t\t\t\"See https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-common-terms-query.html. \"+\n\t\t\t\"You are running Elasticsearch %v.\", esversion)\n\t}\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err = client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Common terms query\n\tq := NewCommonTermsQuery(\"message\", \"Golang\")\n\tsearchResult, err := client.Search().Index(testIndexName).Query(q).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 1 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 1, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 1 {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 1, len(searchResult.Hits.Hits))\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "search_queries_constant_score.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// ConstantScoreQuery is a query that wraps a filter and simply returns\n// a constant score equal to the query boost for every document in the filter.\n//\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-constant-score-query.html\ntype ConstantScoreQuery struct {\n\tfilter Query\n\tboost  *float64\n}\n\n// ConstantScoreQuery creates and initializes a new constant score query.\nfunc NewConstantScoreQuery(filter Query) *ConstantScoreQuery {\n\treturn &ConstantScoreQuery{\n\t\tfilter: filter,\n\t}\n}\n\n// Boost sets the boost for this query. Documents matching this query\n// will (in addition to the normal weightings) have their score multiplied\n// by the boost provided.\nfunc (q *ConstantScoreQuery) Boost(boost float64) *ConstantScoreQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// Source returns the query source.\nfunc (q *ConstantScoreQuery) Source() (interface{}, error) {\n\t// \"constant_score\" : {\n\t//     \"filter\" : {\n\t//         ....\n\t//     },\n\t//     \"boost\" : 1.5\n\t// }\n\n\tquery := make(map[string]interface{})\n\n\tparams := make(map[string]interface{})\n\tquery[\"constant_score\"] = params\n\n\t// filter\n\tsrc, err := q.filter.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tparams[\"filter\"] = src\n\n\t// boost\n\tif q.boost != nil {\n\t\tparams[\"boost\"] = *q.boost\n\t}\n\n\treturn query, nil\n}\n"
  },
  {
    "path": "search_queries_constant_score_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestConstantScoreQuery(t *testing.T) {\n\tq := NewConstantScoreQuery(NewTermQuery(\"user\", \"kimchy\")).Boost(1.2)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"constant_score\":{\"boost\":1.2,\"filter\":{\"term\":{\"user\":\"kimchy\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_dis_max.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// DisMaxQuery is a query that generates the union of documents produced by\n// its subqueries, and that scores each document with the maximum score\n// for that document as produced by any subquery, plus a tie breaking\n// increment for any additional matching subqueries.\n//\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-dis-max-query.html\ntype DisMaxQuery struct {\n\tqueries    []Query\n\tboost      *float64\n\ttieBreaker *float64\n\tqueryName  string\n}\n\n// NewDisMaxQuery creates and initializes a new dis max query.\nfunc NewDisMaxQuery() *DisMaxQuery {\n\treturn &DisMaxQuery{\n\t\tqueries: make([]Query, 0),\n\t}\n}\n\n// Query adds one or more queries to the dis max query.\nfunc (q *DisMaxQuery) Query(queries ...Query) *DisMaxQuery {\n\tq.queries = append(q.queries, queries...)\n\treturn q\n}\n\n// Boost sets the boost for this query. Documents matching this query will\n// (in addition to the normal weightings) have their score multiplied by\n// the boost provided.\nfunc (q *DisMaxQuery) Boost(boost float64) *DisMaxQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// TieBreaker is the factor by which the score of each non-maximum disjunct\n// for a document is multiplied with and added into the final score.\n//\n// If non-zero, the value should be small, on the order of 0.1, which says\n// that 10 occurrences of word in a lower-scored field that is also in a\n// higher scored field is just as good as a unique word in the lower scored\n// field (i.e., one that is not in any higher scored field).\nfunc (q *DisMaxQuery) TieBreaker(tieBreaker float64) *DisMaxQuery {\n\tq.tieBreaker = &tieBreaker\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used\n// when searching for matched filters per hit.\nfunc (q *DisMaxQuery) QueryName(queryName string) *DisMaxQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns the JSON serializable content for this query.\nfunc (q *DisMaxQuery) Source() (interface{}, error) {\n\t// {\n\t//  \"dis_max\" : {\n\t//    \"tie_breaker\" : 0.7,\n\t//    \"boost\" : 1.2,\n\t//    \"queries\" : {\n\t//      {\n\t//        \"term\" : { \"age\" : 34 }\n\t//      },\n\t//      {\n\t//        \"term\" : { \"age\" : 35 }\n\t//      }\n\t//    ]\n\t//  }\n\t// }\n\n\tquery := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tquery[\"dis_max\"] = params\n\n\tif q.tieBreaker != nil {\n\t\tparams[\"tie_breaker\"] = *q.tieBreaker\n\t}\n\tif q.boost != nil {\n\t\tparams[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\n\t// queries\n\tvar clauses []interface{}\n\tfor _, subQuery := range q.queries {\n\t\tsrc, err := subQuery.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tclauses = append(clauses, src)\n\t}\n\tparams[\"queries\"] = clauses\n\n\treturn query, nil\n}\n"
  },
  {
    "path": "search_queries_dis_max_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestDisMaxQuery(t *testing.T) {\n\tq := NewDisMaxQuery()\n\tq = q.Query(NewTermQuery(\"age\", 34), NewTermQuery(\"age\", 35)).Boost(1.2).TieBreaker(0.7)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"dis_max\":{\"boost\":1.2,\"queries\":[{\"term\":{\"age\":34}},{\"term\":{\"age\":35}}],\"tie_breaker\":0.7}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_distance_feature_query.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"fmt\"\n)\n\n// DistanceFeatureQuery uses a script to provide a custom score for returned documents.\n//\n// A DistanceFeatureQuery query is useful if, for example, a scoring function is\n// expensive and you only need to calculate the score of a filtered set of documents.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-distance-feature-query.html\ntype DistanceFeatureQuery struct {\n\tfield     string\n\tpivot     string\n\torigin    interface{}\n\tboost     *float64\n\tqueryName string\n}\n\n// NewDistanceFeatureQuery creates and initializes a new script_score query.\nfunc NewDistanceFeatureQuery(field string, origin interface{}, pivot string) *DistanceFeatureQuery {\n\treturn &DistanceFeatureQuery{\n\t\tfield:  field,\n\t\torigin: origin,\n\t\tpivot:  pivot,\n\t}\n}\n\n// Field to be used in the DistanceFeatureQuery.\nfunc (q *DistanceFeatureQuery) Field(name string) *DistanceFeatureQuery {\n\tq.field = name\n\treturn q\n}\n\n// Origin is the date or point of origin used to calculate distances.\n//\n// If the field is a date or date_nanos field, the origin value must be a\n// date. Date math such as \"now-1h\" is supported.\n//\n// If the field is a geo_point field, the origin must be a GeoPoint.\nfunc (q *DistanceFeatureQuery) Origin(origin interface{}) *DistanceFeatureQuery {\n\tq.origin = origin\n\treturn q\n}\n\n// Pivot is distance from the origin at which relevance scores\n// receive half of the boost value.\n//\n// If field is a date or date_nanos field, the pivot value must be a time\n// unit, such as \"1h\" or \"10d\".\n//\n// If field is a geo_point field, the pivot value must be a distance unit,\n// such as \"1km\" or \"12m\". You can pass a string, or a GeoPoint.\nfunc (q *DistanceFeatureQuery) Pivot(pivot string) *DistanceFeatureQuery {\n\tq.pivot = pivot\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *DistanceFeatureQuery) Boost(boost float64) *DistanceFeatureQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter.\nfunc (q *DistanceFeatureQuery) QueryName(queryName string) *DistanceFeatureQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *DistanceFeatureQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"distance_feature\" : {\n\t//     \"field\" : \"production_date\",\n\t//     \"pivot\" : \"7d\",\n\t//     \"origin\" : \"now\"\n\t//\t }\n\t// }\n\t// {\n\t//   \"distance_feature\" : {\n\t//     \"field\" : \"location\",\n\t//     \"pivot\" : \"1000m\",\n\t//     \"origin\" : [-71.3, 41.15]\n\t//\t }\n\t// }\n\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"distance_feature\"] = query\n\n\tquery[\"field\"] = q.field\n\tquery[\"pivot\"] = q.pivot\n\tswitch v := q.origin.(type) {\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"DistanceFeatureQuery: unable to serialize Origin from type %T\", v)\n\tcase string:\n\t\tquery[\"origin\"] = v\n\tcase *GeoPoint:\n\t\tquery[\"origin\"] = v.Source()\n\tcase GeoPoint:\n\t\tquery[\"origin\"] = v.Source()\n\t}\n\n\tif v := q.boost; v != nil {\n\t\tquery[\"boost\"] = *v\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_distance_feature_query_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestDistanceFeatureQueryForDateField(t *testing.T) {\n\tq := NewDistanceFeatureQuery(\"production_date\", \"now\", \"7d\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"distance_feature\":{\"field\":\"production_date\",\"origin\":\"now\",\"pivot\":\"7d\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDistanceFeatureQueryForGeoField(t *testing.T) {\n\tq := NewDistanceFeatureQuery(\"location\", GeoPointFromLatLon(-71.3, 41.15), \"1000m\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"distance_feature\":{\"field\":\"location\",\"origin\":{\"lat\":-71.3,\"lon\":41.15},\"pivot\":\"1000m\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestDistanceFeatureQueryIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tres, err := client.Search().\n\t\tIndex(testOrderIndex).\n\t\tQuery(\n\t\t\tNewDistanceFeatureQuery(\"time\", \"now\", \"7d\"),\n\t\t).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got nil\")\n\t}\n\tif want, have := int64(8), res.TotalHits(); want != have {\n\t\tt.Errorf(\"expected TotalHits() = %d; got %d\", want, have)\n\t}\n\tif want, have := 8, len(res.Hits.Hits); want != have {\n\t\tt.Errorf(\"expected len(Hits.Hits) = %d; got %d\", want, have)\n\t}\n}\n"
  },
  {
    "path": "search_queries_exists.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// ExistsQuery is a query that only matches on documents that the field\n// has a value in them.\n//\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-exists-query.html\ntype ExistsQuery struct {\n\tname      string\n\tqueryName string\n}\n\n// NewExistsQuery creates and initializes a new exists query.\nfunc NewExistsQuery(name string) *ExistsQuery {\n\treturn &ExistsQuery{\n\t\tname: name,\n\t}\n}\n\n// QueryName sets the query name for the filter that can be used\n// when searching for matched queries per hit.\nfunc (q *ExistsQuery) QueryName(queryName string) *ExistsQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns the JSON serializable content for this query.\nfunc (q *ExistsQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"exists\" : {\n\t//     \"field\" : \"user\"\n\t//   }\n\t// }\n\n\tquery := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tquery[\"exists\"] = params\n\n\tparams[\"field\"] = q.name\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\n\treturn query, nil\n}\n"
  },
  {
    "path": "search_queries_exists_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestExistsQuery(t *testing.T) {\n\tq := NewExistsQuery(\"user\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"exists\":{\"field\":\"user\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_fsq.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// FunctionScoreQuery allows you to modify the score of documents that\n// are retrieved by a query. This can be useful if, for example,\n// a score function is computationally expensive and it is sufficient\n// to compute the score on a filtered set of documents.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html\ntype FunctionScoreQuery struct {\n\tquery      Query\n\tfilter     Query\n\tboost      *float64\n\tmaxBoost   *float64\n\tscoreMode  string\n\tboostMode  string\n\tfilters    []Query\n\tscoreFuncs []ScoreFunction\n\tminScore   *float64\n}\n\n// NewFunctionScoreQuery creates and initializes a new function score query.\nfunc NewFunctionScoreQuery() *FunctionScoreQuery {\n\treturn &FunctionScoreQuery{\n\t\tfilters:    make([]Query, 0),\n\t\tscoreFuncs: make([]ScoreFunction, 0),\n\t}\n}\n\n// Query sets the query for the function score query.\nfunc (q *FunctionScoreQuery) Query(query Query) *FunctionScoreQuery {\n\tq.query = query\n\treturn q\n}\n\n// Filter sets the filter for the function score query.\nfunc (q *FunctionScoreQuery) Filter(filter Query) *FunctionScoreQuery {\n\tq.filter = filter\n\treturn q\n}\n\n// Add adds a score function that will execute on all the documents\n// matching the filter.\nfunc (q *FunctionScoreQuery) Add(filter Query, scoreFunc ScoreFunction) *FunctionScoreQuery {\n\tq.filters = append(q.filters, filter)\n\tq.scoreFuncs = append(q.scoreFuncs, scoreFunc)\n\treturn q\n}\n\n// AddScoreFunc adds a score function that will execute the function on all documents.\nfunc (q *FunctionScoreQuery) AddScoreFunc(scoreFunc ScoreFunction) *FunctionScoreQuery {\n\tq.filters = append(q.filters, nil)\n\tq.scoreFuncs = append(q.scoreFuncs, scoreFunc)\n\treturn q\n}\n\n// ScoreMode defines how results of individual score functions will be aggregated.\n// Can be first, avg, max, sum, min, or multiply.\nfunc (q *FunctionScoreQuery) ScoreMode(scoreMode string) *FunctionScoreQuery {\n\tq.scoreMode = scoreMode\n\treturn q\n}\n\n// BoostMode defines how the combined result of score functions will\n// influence the final score together with the sub query score.\nfunc (q *FunctionScoreQuery) BoostMode(boostMode string) *FunctionScoreQuery {\n\tq.boostMode = boostMode\n\treturn q\n}\n\n// MaxBoost is the maximum boost that will be applied by function score.\nfunc (q *FunctionScoreQuery) MaxBoost(maxBoost float64) *FunctionScoreQuery {\n\tq.maxBoost = &maxBoost\n\treturn q\n}\n\n// Boost sets the boost for this query. Documents matching this query will\n// (in addition to the normal weightings) have their score multiplied by the\n// boost provided.\nfunc (q *FunctionScoreQuery) Boost(boost float64) *FunctionScoreQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// MinScore sets the minimum score.\nfunc (q *FunctionScoreQuery) MinScore(minScore float64) *FunctionScoreQuery {\n\tq.minScore = &minScore\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *FunctionScoreQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"function_score\"] = query\n\n\tif q.query != nil {\n\t\tsrc, err := q.query.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tquery[\"query\"] = src\n\t}\n\tif q.filter != nil {\n\t\tsrc, err := q.filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tquery[\"filter\"] = src\n\t}\n\n\tif len(q.filters) > 0 {\n\t\tfuncs := make([]interface{}, len(q.filters))\n\t\tfor i, filter := range q.filters {\n\t\t\thsh := make(map[string]interface{})\n\t\t\tif filter != nil {\n\t\t\t\tsrc, err := filter.Source()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\thsh[\"filter\"] = src\n\t\t\t}\n\t\t\t// Weight needs to be serialized on this level.\n\t\t\tif weight := q.scoreFuncs[i].GetWeight(); weight != nil {\n\t\t\t\thsh[\"weight\"] = weight\n\t\t\t}\n\t\t\t// Serialize the score function\n\t\t\tsrc, err := q.scoreFuncs[i].Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\thsh[q.scoreFuncs[i].Name()] = src\n\t\t\tfuncs[i] = hsh\n\t\t}\n\t\tquery[\"functions\"] = funcs\n\t}\n\n\tif q.scoreMode != \"\" {\n\t\tquery[\"score_mode\"] = q.scoreMode\n\t}\n\tif q.boostMode != \"\" {\n\t\tquery[\"boost_mode\"] = q.boostMode\n\t}\n\tif q.maxBoost != nil {\n\t\tquery[\"max_boost\"] = *q.maxBoost\n\t}\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.minScore != nil {\n\t\tquery[\"min_score\"] = *q.minScore\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_fsq_score_funcs.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"strings\"\n)\n\n// ScoreFunction is used in combination with the Function Score Query.\ntype ScoreFunction interface {\n\tName() string\n\tGetWeight() *float64 // returns the weight which must be serialized at the level of FunctionScoreQuery\n\tSource() (interface{}, error)\n}\n\n// -- Exponential Decay --\n\n// ExponentialDecayFunction builds an exponential decay score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html\n// for details.\ntype ExponentialDecayFunction struct {\n\tfieldName      string\n\torigin         interface{}\n\tscale          interface{}\n\tdecay          *float64\n\toffset         interface{}\n\tmultiValueMode string\n\tweight         *float64\n}\n\n// NewExponentialDecayFunction creates a new ExponentialDecayFunction.\nfunc NewExponentialDecayFunction() *ExponentialDecayFunction {\n\treturn &ExponentialDecayFunction{}\n}\n\n// Name represents the JSON field name under which the output of Source\n// needs to be serialized by FunctionScoreQuery (see FunctionScoreQuery.Source).\nfunc (fn *ExponentialDecayFunction) Name() string {\n\treturn \"exp\"\n}\n\n// FieldName specifies the name of the field to which this decay function is applied to.\nfunc (fn *ExponentialDecayFunction) FieldName(fieldName string) *ExponentialDecayFunction {\n\tfn.fieldName = fieldName\n\treturn fn\n}\n\n// Origin defines the \"central point\" by which the decay function calculates\n// \"distance\".\nfunc (fn *ExponentialDecayFunction) Origin(origin interface{}) *ExponentialDecayFunction {\n\tfn.origin = origin\n\treturn fn\n}\n\n// Scale defines the scale to be used with Decay.\nfunc (fn *ExponentialDecayFunction) Scale(scale interface{}) *ExponentialDecayFunction {\n\tfn.scale = scale\n\treturn fn\n}\n\n// Decay defines how documents are scored at the distance given a Scale.\n// If no decay is defined, documents at the distance Scale will be scored 0.5.\nfunc (fn *ExponentialDecayFunction) Decay(decay float64) *ExponentialDecayFunction {\n\tfn.decay = &decay\n\treturn fn\n}\n\n// Offset, if defined, computes the decay function only for a distance\n// greater than the defined offset.\nfunc (fn *ExponentialDecayFunction) Offset(offset interface{}) *ExponentialDecayFunction {\n\tfn.offset = offset\n\treturn fn\n}\n\n// Weight adjusts the score of the score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_using_function_score\n// for details.\nfunc (fn *ExponentialDecayFunction) Weight(weight float64) *ExponentialDecayFunction {\n\tfn.weight = &weight\n\treturn fn\n}\n\n// GetWeight returns the adjusted score. It is part of the ScoreFunction interface.\n// Returns nil if weight is not specified.\nfunc (fn *ExponentialDecayFunction) GetWeight() *float64 {\n\treturn fn.weight\n}\n\n// MultiValueMode specifies how the decay function should be calculated\n// on a field that has multiple values.\n// Valid modes are: min, max, avg, and sum.\nfunc (fn *ExponentialDecayFunction) MultiValueMode(mode string) *ExponentialDecayFunction {\n\tfn.multiValueMode = mode\n\treturn fn\n}\n\n// Source returns the serializable JSON data of this score function.\nfunc (fn *ExponentialDecayFunction) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[fn.fieldName] = params\n\tif fn.origin != nil {\n\t\tparams[\"origin\"] = fn.origin\n\t}\n\tparams[\"scale\"] = fn.scale\n\tif fn.decay != nil && *fn.decay > 0 {\n\t\tparams[\"decay\"] = *fn.decay\n\t}\n\tif fn.offset != nil {\n\t\tparams[\"offset\"] = fn.offset\n\t}\n\tif fn.multiValueMode != \"\" {\n\t\tsource[\"multi_value_mode\"] = fn.multiValueMode\n\t}\n\treturn source, nil\n}\n\n// -- Gauss Decay --\n\n// GaussDecayFunction builds a gauss decay score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html\n// for details.\ntype GaussDecayFunction struct {\n\tfieldName      string\n\torigin         interface{}\n\tscale          interface{}\n\tdecay          *float64\n\toffset         interface{}\n\tmultiValueMode string\n\tweight         *float64\n}\n\n// NewGaussDecayFunction returns a new GaussDecayFunction.\nfunc NewGaussDecayFunction() *GaussDecayFunction {\n\treturn &GaussDecayFunction{}\n}\n\n// Name represents the JSON field name under which the output of Source\n// needs to be serialized by FunctionScoreQuery (see FunctionScoreQuery.Source).\nfunc (fn *GaussDecayFunction) Name() string {\n\treturn \"gauss\"\n}\n\n// FieldName specifies the name of the field to which this decay function is applied to.\nfunc (fn *GaussDecayFunction) FieldName(fieldName string) *GaussDecayFunction {\n\tfn.fieldName = fieldName\n\treturn fn\n}\n\n// Origin defines the \"central point\" by which the decay function calculates\n// \"distance\".\nfunc (fn *GaussDecayFunction) Origin(origin interface{}) *GaussDecayFunction {\n\tfn.origin = origin\n\treturn fn\n}\n\n// Scale defines the scale to be used with Decay.\nfunc (fn *GaussDecayFunction) Scale(scale interface{}) *GaussDecayFunction {\n\tfn.scale = scale\n\treturn fn\n}\n\n// Decay defines how documents are scored at the distance given a Scale.\n// If no decay is defined, documents at the distance Scale will be scored 0.5.\nfunc (fn *GaussDecayFunction) Decay(decay float64) *GaussDecayFunction {\n\tfn.decay = &decay\n\treturn fn\n}\n\n// Offset, if defined, computes the decay function only for a distance\n// greater than the defined offset.\nfunc (fn *GaussDecayFunction) Offset(offset interface{}) *GaussDecayFunction {\n\tfn.offset = offset\n\treturn fn\n}\n\n// Weight adjusts the score of the score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_using_function_score\n// for details.\nfunc (fn *GaussDecayFunction) Weight(weight float64) *GaussDecayFunction {\n\tfn.weight = &weight\n\treturn fn\n}\n\n// GetWeight returns the adjusted score. It is part of the ScoreFunction interface.\n// Returns nil if weight is not specified.\nfunc (fn *GaussDecayFunction) GetWeight() *float64 {\n\treturn fn.weight\n}\n\n// MultiValueMode specifies how the decay function should be calculated\n// on a field that has multiple values.\n// Valid modes are: min, max, avg, and sum.\nfunc (fn *GaussDecayFunction) MultiValueMode(mode string) *GaussDecayFunction {\n\tfn.multiValueMode = mode\n\treturn fn\n}\n\n// Source returns the serializable JSON data of this score function.\nfunc (fn *GaussDecayFunction) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[fn.fieldName] = params\n\tif fn.origin != nil {\n\t\tparams[\"origin\"] = fn.origin\n\t}\n\tparams[\"scale\"] = fn.scale\n\tif fn.decay != nil && *fn.decay > 0 {\n\t\tparams[\"decay\"] = *fn.decay\n\t}\n\tif fn.offset != nil {\n\t\tparams[\"offset\"] = fn.offset\n\t}\n\tif fn.multiValueMode != \"\" {\n\t\tsource[\"multi_value_mode\"] = fn.multiValueMode\n\t}\n\t// Notice that the weight has to be serialized in FunctionScoreQuery.\n\treturn source, nil\n}\n\n// -- Linear Decay --\n\n// LinearDecayFunction builds a linear decay score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html\n// for details.\ntype LinearDecayFunction struct {\n\tfieldName      string\n\torigin         interface{}\n\tscale          interface{}\n\tdecay          *float64\n\toffset         interface{}\n\tmultiValueMode string\n\tweight         *float64\n}\n\n// NewLinearDecayFunction initializes and returns a new LinearDecayFunction.\nfunc NewLinearDecayFunction() *LinearDecayFunction {\n\treturn &LinearDecayFunction{}\n}\n\n// Name represents the JSON field name under which the output of Source\n// needs to be serialized by FunctionScoreQuery (see FunctionScoreQuery.Source).\nfunc (fn *LinearDecayFunction) Name() string {\n\treturn \"linear\"\n}\n\n// FieldName specifies the name of the field to which this decay function is applied to.\nfunc (fn *LinearDecayFunction) FieldName(fieldName string) *LinearDecayFunction {\n\tfn.fieldName = fieldName\n\treturn fn\n}\n\n// Origin defines the \"central point\" by which the decay function calculates\n// \"distance\".\nfunc (fn *LinearDecayFunction) Origin(origin interface{}) *LinearDecayFunction {\n\tfn.origin = origin\n\treturn fn\n}\n\n// Scale defines the scale to be used with Decay.\nfunc (fn *LinearDecayFunction) Scale(scale interface{}) *LinearDecayFunction {\n\tfn.scale = scale\n\treturn fn\n}\n\n// Decay defines how documents are scored at the distance given a Scale.\n// If no decay is defined, documents at the distance Scale will be scored 0.5.\nfunc (fn *LinearDecayFunction) Decay(decay float64) *LinearDecayFunction {\n\tfn.decay = &decay\n\treturn fn\n}\n\n// Offset, if defined, computes the decay function only for a distance\n// greater than the defined offset.\nfunc (fn *LinearDecayFunction) Offset(offset interface{}) *LinearDecayFunction {\n\tfn.offset = offset\n\treturn fn\n}\n\n// Weight adjusts the score of the score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_using_function_score\n// for details.\nfunc (fn *LinearDecayFunction) Weight(weight float64) *LinearDecayFunction {\n\tfn.weight = &weight\n\treturn fn\n}\n\n// GetWeight returns the adjusted score. It is part of the ScoreFunction interface.\n// Returns nil if weight is not specified.\nfunc (fn *LinearDecayFunction) GetWeight() *float64 {\n\treturn fn.weight\n}\n\n// MultiValueMode specifies how the decay function should be calculated\n// on a field that has multiple values.\n// Valid modes are: min, max, avg, and sum.\nfunc (fn *LinearDecayFunction) MultiValueMode(mode string) *LinearDecayFunction {\n\tfn.multiValueMode = mode\n\treturn fn\n}\n\n// GetMultiValueMode returns how the decay function should be calculated\n// on a field that has multiple values.\n// Valid modes are: min, max, avg, and sum.\nfunc (fn *LinearDecayFunction) GetMultiValueMode() string {\n\treturn fn.multiValueMode\n}\n\n// Source returns the serializable JSON data of this score function.\nfunc (fn *LinearDecayFunction) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[fn.fieldName] = params\n\tif fn.origin != nil {\n\t\tparams[\"origin\"] = fn.origin\n\t}\n\tparams[\"scale\"] = fn.scale\n\tif fn.decay != nil && *fn.decay > 0 {\n\t\tparams[\"decay\"] = *fn.decay\n\t}\n\tif fn.offset != nil {\n\t\tparams[\"offset\"] = fn.offset\n\t}\n\tif fn.multiValueMode != \"\" {\n\t\tsource[\"multi_value_mode\"] = fn.multiValueMode\n\t}\n\t// Notice that the weight has to be serialized in FunctionScoreQuery.\n\treturn source, nil\n}\n\n// -- Script --\n\n// ScriptFunction builds a script score function. It uses a script to\n// compute or influence the score of documents that match with the inner\n// query or filter.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_script_score\n// for details.\ntype ScriptFunction struct {\n\tscript *Script\n\tweight *float64\n}\n\n// NewScriptFunction initializes and returns a new ScriptFunction.\nfunc NewScriptFunction(script *Script) *ScriptFunction {\n\treturn &ScriptFunction{\n\t\tscript: script,\n\t}\n}\n\n// Name represents the JSON field name under which the output of Source\n// needs to be serialized by FunctionScoreQuery (see FunctionScoreQuery.Source).\nfunc (fn *ScriptFunction) Name() string {\n\treturn \"script_score\"\n}\n\n// Script specifies the script to be executed.\nfunc (fn *ScriptFunction) Script(script *Script) *ScriptFunction {\n\tfn.script = script\n\treturn fn\n}\n\n// Weight adjusts the score of the score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_using_function_score\n// for details.\nfunc (fn *ScriptFunction) Weight(weight float64) *ScriptFunction {\n\tfn.weight = &weight\n\treturn fn\n}\n\n// GetWeight returns the adjusted score. It is part of the ScoreFunction interface.\n// Returns nil if weight is not specified.\nfunc (fn *ScriptFunction) GetWeight() *float64 {\n\treturn fn.weight\n}\n\n// Source returns the serializable JSON data of this score function.\nfunc (fn *ScriptFunction) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif fn.script != nil {\n\t\tsrc, err := fn.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"script\"] = src\n\t}\n\t// Notice that the weight has to be serialized in FunctionScoreQuery.\n\treturn source, nil\n}\n\n// -- Field value factor --\n\n// FieldValueFactorFunction is a function score function that allows you\n// to use a field from a document to influence the score.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_field_value_factor.\ntype FieldValueFactorFunction struct {\n\tfield    string\n\tfactor   *float64\n\tmissing  *float64\n\tweight   *float64\n\tmodifier string\n}\n\n// NewFieldValueFactorFunction initializes and returns a new FieldValueFactorFunction.\nfunc NewFieldValueFactorFunction() *FieldValueFactorFunction {\n\treturn &FieldValueFactorFunction{}\n}\n\n// Name represents the JSON field name under which the output of Source\n// needs to be serialized by FunctionScoreQuery (see FunctionScoreQuery.Source).\nfunc (fn *FieldValueFactorFunction) Name() string {\n\treturn \"field_value_factor\"\n}\n\n// Field is the field to be extracted from the document.\nfunc (fn *FieldValueFactorFunction) Field(field string) *FieldValueFactorFunction {\n\tfn.field = field\n\treturn fn\n}\n\n// Factor is the (optional) factor to multiply the field with. If you do not\n// specify a factor, the default is 1.\nfunc (fn *FieldValueFactorFunction) Factor(factor float64) *FieldValueFactorFunction {\n\tfn.factor = &factor\n\treturn fn\n}\n\n// Modifier to apply to the field value. It can be one of: none, log, log1p,\n// log2p, ln, ln1p, ln2p, square, sqrt, or reciprocal. Defaults to: none.\nfunc (fn *FieldValueFactorFunction) Modifier(modifier string) *FieldValueFactorFunction {\n\tfn.modifier = modifier\n\treturn fn\n}\n\n// Weight adjusts the score of the score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_using_function_score\n// for details.\nfunc (fn *FieldValueFactorFunction) Weight(weight float64) *FieldValueFactorFunction {\n\tfn.weight = &weight\n\treturn fn\n}\n\n// GetWeight returns the adjusted score. It is part of the ScoreFunction interface.\n// Returns nil if weight is not specified.\nfunc (fn *FieldValueFactorFunction) GetWeight() *float64 {\n\treturn fn.weight\n}\n\n// Missing is used if a document does not have that field.\nfunc (fn *FieldValueFactorFunction) Missing(missing float64) *FieldValueFactorFunction {\n\tfn.missing = &missing\n\treturn fn\n}\n\n// Source returns the serializable JSON data of this score function.\nfunc (fn *FieldValueFactorFunction) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif fn.field != \"\" {\n\t\tsource[\"field\"] = fn.field\n\t}\n\tif fn.factor != nil {\n\t\tsource[\"factor\"] = *fn.factor\n\t}\n\tif fn.missing != nil {\n\t\tsource[\"missing\"] = *fn.missing\n\t}\n\tif fn.modifier != \"\" {\n\t\tsource[\"modifier\"] = strings.ToLower(fn.modifier)\n\t}\n\t// Notice that the weight has to be serialized in FunctionScoreQuery.\n\treturn source, nil\n}\n\n// -- Weight Factor --\n\n// WeightFactorFunction builds a weight factor function that multiplies\n// the weight to the score.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_weight\n// for details.\ntype WeightFactorFunction struct {\n\tweight float64\n}\n\n// NewWeightFactorFunction initializes and returns a new WeightFactorFunction.\nfunc NewWeightFactorFunction(weight float64) *WeightFactorFunction {\n\treturn &WeightFactorFunction{weight: weight}\n}\n\n// Name represents the JSON field name under which the output of Source\n// needs to be serialized by FunctionScoreQuery (see FunctionScoreQuery.Source).\nfunc (fn *WeightFactorFunction) Name() string {\n\treturn \"weight\"\n}\n\n// Weight adjusts the score of the score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_using_function_score\n// for details.\nfunc (fn *WeightFactorFunction) Weight(weight float64) *WeightFactorFunction {\n\tfn.weight = weight\n\treturn fn\n}\n\n// GetWeight returns the adjusted score. It is part of the ScoreFunction interface.\n// Returns nil if weight is not specified.\nfunc (fn *WeightFactorFunction) GetWeight() *float64 {\n\treturn &fn.weight\n}\n\n// Source returns the serializable JSON data of this score function.\nfunc (fn *WeightFactorFunction) Source() (interface{}, error) {\n\t// Notice that the weight has to be serialized in FunctionScoreQuery.\n\treturn fn.weight, nil\n}\n\n// -- Random --\n\n// RandomFunction builds a random score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_random\n// for details.\ntype RandomFunction struct {\n\tfield  string\n\tseed   interface{}\n\tweight *float64\n}\n\n// NewRandomFunction initializes and returns a new RandomFunction.\nfunc NewRandomFunction() *RandomFunction {\n\treturn &RandomFunction{}\n}\n\n// Name represents the JSON field name under which the output of Source\n// needs to be serialized by FunctionScoreQuery (see FunctionScoreQuery.Source).\nfunc (fn *RandomFunction) Name() string {\n\treturn \"random_score\"\n}\n\n// Field is the field to be used for random number generation.\n// This parameter is compulsory when a Seed is set and ignored\n// otherwise. Note that documents that have the same value for a\n// field will get the same score.\nfunc (fn *RandomFunction) Field(field string) *RandomFunction {\n\tfn.field = field\n\treturn fn\n}\n\n// Seed sets the seed based on which the random number will be generated.\n// Using the same seed is guaranteed to generate the same random number for a specific doc.\n// Seed must be an integer, e.g. int or int64. It is specified as an interface{}\n// here for compatibility with older versions (which also accepted strings).\nfunc (fn *RandomFunction) Seed(seed interface{}) *RandomFunction {\n\tfn.seed = seed\n\treturn fn\n}\n\n// Weight adjusts the score of the score function.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-function-score-query.html#_using_function_score\n// for details.\nfunc (fn *RandomFunction) Weight(weight float64) *RandomFunction {\n\tfn.weight = &weight\n\treturn fn\n}\n\n// GetWeight returns the adjusted score. It is part of the ScoreFunction interface.\n// Returns nil if weight is not specified.\nfunc (fn *RandomFunction) GetWeight() *float64 {\n\treturn fn.weight\n}\n\n// Source returns the serializable JSON data of this score function.\nfunc (fn *RandomFunction) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif fn.field != \"\" {\n\t\tsource[\"field\"] = fn.field\n\t}\n\tif fn.seed != nil {\n\t\tsource[\"seed\"] = fn.seed\n\t}\n\t// Notice that the weight has to be serialized in FunctionScoreQuery.\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_fsq_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestFunctionScoreQuery(t *testing.T) {\n\tq := NewFunctionScoreQuery().\n\t\tQuery(NewTermQuery(\"name.last\", \"banon\")).\n\t\tAdd(NewTermQuery(\"name.last\", \"banon\"), NewWeightFactorFunction(1.5)).\n\t\tAddScoreFunc(NewWeightFactorFunction(3)).\n\t\tAddScoreFunc(NewRandomFunction().Field(\"_seq_no\").Seed(10)).\n\t\tBoost(3).\n\t\tMaxBoost(10).\n\t\tScoreMode(\"avg\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"function_score\":{\"boost\":3,\"functions\":[{\"filter\":{\"term\":{\"name.last\":\"banon\"}},\"weight\":1.5},{\"weight\":3},{\"random_score\":{\"field\":\"_seq_no\",\"seed\":10}}],\"max_boost\":10,\"query\":{\"term\":{\"name.last\":\"banon\"}},\"score_mode\":\"avg\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFunctionScoreQueryWithNilFilter(t *testing.T) {\n\tq := NewFunctionScoreQuery().\n\t\tQuery(NewTermQuery(\"tag\", \"wow\")).\n\t\tAddScoreFunc(NewRandomFunction()).\n\t\tBoost(2.0).\n\t\tMaxBoost(12.0).\n\t\tBoostMode(\"multiply\").\n\t\tScoreMode(\"max\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"function_score\":{\"boost\":2,\"boost_mode\":\"multiply\",\"functions\":[{\"random_score\":{}}],\"max_boost\":12,\"query\":{\"term\":{\"tag\":\"wow\"}},\"score_mode\":\"max\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFieldValueFactor(t *testing.T) {\n\tq := NewFunctionScoreQuery().\n\t\tQuery(NewTermQuery(\"name.last\", \"banon\")).\n\t\tAddScoreFunc(NewFieldValueFactorFunction().Modifier(\"sqrt\").Factor(2).Field(\"income\")).\n\t\tBoost(2.0).\n\t\tMaxBoost(12.0).\n\t\tBoostMode(\"multiply\").\n\t\tScoreMode(\"max\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"function_score\":{\"boost\":2,\"boost_mode\":\"multiply\",\"functions\":[{\"field_value_factor\":{\"factor\":2,\"field\":\"income\",\"modifier\":\"sqrt\"}}],\"max_boost\":12,\"query\":{\"term\":{\"name.last\":\"banon\"}},\"score_mode\":\"max\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFieldValueFactorWithWeight(t *testing.T) {\n\tq := NewFunctionScoreQuery().\n\t\tQuery(NewTermQuery(\"name.last\", \"banon\")).\n\t\tAddScoreFunc(NewFieldValueFactorFunction().Modifier(\"sqrt\").Factor(2).Field(\"income\").Weight(2.5)).\n\t\tBoost(2.0).\n\t\tMaxBoost(12.0).\n\t\tBoostMode(\"multiply\").\n\t\tScoreMode(\"max\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"function_score\":{\"boost\":2,\"boost_mode\":\"multiply\",\"functions\":[{\"field_value_factor\":{\"factor\":2,\"field\":\"income\",\"modifier\":\"sqrt\"},\"weight\":2.5}],\"max_boost\":12,\"query\":{\"term\":{\"name.last\":\"banon\"}},\"score_mode\":\"max\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFieldValueFactorWithMultipleScoreFuncsAndWeights(t *testing.T) {\n\tq := NewFunctionScoreQuery().\n\t\tQuery(NewTermQuery(\"name.last\", \"banon\")).\n\t\tAddScoreFunc(NewFieldValueFactorFunction().Modifier(\"sqrt\").Factor(2).Field(\"income\").Weight(2.5)).\n\t\tAddScoreFunc(NewScriptFunction(NewScript(\"_score * doc['my_numeric_field'].value\")).Weight(1.25)).\n\t\tAddScoreFunc(NewWeightFactorFunction(0.5)).\n\t\tBoost(2.0).\n\t\tMaxBoost(12.0).\n\t\tBoostMode(\"multiply\").\n\t\tScoreMode(\"max\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"function_score\":{\"boost\":2,\"boost_mode\":\"multiply\",\"functions\":[{\"field_value_factor\":{\"factor\":2,\"field\":\"income\",\"modifier\":\"sqrt\"},\"weight\":2.5},{\"script_score\":{\"script\":{\"source\":\"_score * doc['my_numeric_field'].value\"}},\"weight\":1.25},{\"weight\":0.5}],\"max_boost\":12,\"query\":{\"term\":{\"name.last\":\"banon\"}},\"score_mode\":\"max\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFunctionScoreQueryWithGaussScoreFunc(t *testing.T) {\n\tq := NewFunctionScoreQuery().\n\t\tQuery(NewTermQuery(\"name.last\", \"banon\")).\n\t\tAddScoreFunc(NewGaussDecayFunction().FieldName(\"pin.location\").Origin(\"11, 12\").Scale(\"2km\").Offset(\"0km\").Decay(0.33))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"function_score\":{\"functions\":[{\"gauss\":{\"pin.location\":{\"decay\":0.33,\"offset\":\"0km\",\"origin\":\"11, 12\",\"scale\":\"2km\"}}}],\"query\":{\"term\":{\"name.last\":\"banon\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFunctionScoreQueryWithGaussScoreFuncAndMultiValueMode(t *testing.T) {\n\tq := NewFunctionScoreQuery().\n\t\tQuery(NewTermQuery(\"name.last\", \"banon\")).\n\t\tAddScoreFunc(NewGaussDecayFunction().FieldName(\"pin.location\").Origin(\"11, 12\").Scale(\"2km\").Offset(\"0km\").Decay(0.33).MultiValueMode(\"avg\"))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"function_score\":{\"functions\":[{\"gauss\":{\"multi_value_mode\":\"avg\",\"pin.location\":{\"decay\":0.33,\"offset\":\"0km\",\"origin\":\"11, 12\",\"scale\":\"2km\"}}}],\"query\":{\"term\":{\"name.last\":\"banon\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFunctionScoreQueryWithFilters(t *testing.T) {\n\tq := NewFunctionScoreQuery().\n\t\tAdd(NewTermQuery(\"features\", \"wifi\"), NewWeightFactorFunction(1)).\n\t\tAdd(NewTermQuery(\"features\", \"garden\"), NewWeightFactorFunction(1)).\n\t\tAdd(NewTermQuery(\"features\", \"pool\"), NewWeightFactorFunction(2)).\n\t\tScoreMode(\"sum\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"function_score\":{\"functions\":[{\"filter\":{\"term\":{\"features\":\"wifi\"}},\"weight\":1},{\"filter\":{\"term\":{\"features\":\"garden\"}},\"weight\":1},{\"filter\":{\"term\":{\"features\":\"pool\"}},\"weight\":2}],\"score_mode\":\"sum\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFunctionScoreQueryBug660(t *testing.T) {\n\tq := NewFunctionScoreQuery().\n\t\tQuery(NewBoolQuery().Filter(NewTermsQuery(\"prod\", 8199))).\n\t\tAddScoreFunc(\n\t\t\tNewGaussDecayFunction().\n\t\t\t\tFieldName(\"update\").\n\t\t\t\tOrigin(1501747403).\n\t\t\t\tScale(1209600).\n\t\t\t\tOffset(\"259200\").\n\t\t\t\tDecay(0.6).\n\t\t\t\tWeight(1),\n\t\t).\n\t\tBoostMode(\"sum\").\n\t\tScoreMode(\"sum\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"function_score\":{\"boost_mode\":\"sum\",\"functions\":[{\"gauss\":{\"update\":{\"decay\":0.6,\"offset\":\"259200\",\"origin\":1501747403,\"scale\":1209600}},\"weight\":1}],\"query\":{\"bool\":{\"filter\":{\"terms\":{\"prod\":[8199]}}}},\"score_mode\":\"sum\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_fuzzy.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// FuzzyQuery uses similarity based on Levenshtein edit distance for\n// string fields, and a +/- margin on numeric and date fields.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-fuzzy-query.html\ntype FuzzyQuery struct {\n\tname           string\n\tvalue          interface{}\n\tboost          *float64\n\tfuzziness      interface{}\n\tprefixLength   *int\n\tmaxExpansions  *int\n\ttranspositions *bool\n\trewrite        string\n\tqueryName      string\n}\n\n// NewFuzzyQuery creates a new fuzzy query.\nfunc NewFuzzyQuery(name string, value interface{}) *FuzzyQuery {\n\tq := &FuzzyQuery{\n\t\tname:  name,\n\t\tvalue: value,\n\t}\n\treturn q\n}\n\n// Boost sets the boost for this query. Documents matching this query will\n// (in addition to the normal weightings) have their score multiplied by\n// the boost provided.\nfunc (q *FuzzyQuery) Boost(boost float64) *FuzzyQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// Fuzziness can be an integer/long like 0, 1 or 2 as well as strings\n// like \"auto\", \"0..1\", \"1..4\" or \"0.0..1.0\".\nfunc (q *FuzzyQuery) Fuzziness(fuzziness interface{}) *FuzzyQuery {\n\tq.fuzziness = fuzziness\n\treturn q\n}\n\nfunc (q *FuzzyQuery) PrefixLength(prefixLength int) *FuzzyQuery {\n\tq.prefixLength = &prefixLength\n\treturn q\n}\n\nfunc (q *FuzzyQuery) MaxExpansions(maxExpansions int) *FuzzyQuery {\n\tq.maxExpansions = &maxExpansions\n\treturn q\n}\n\nfunc (q *FuzzyQuery) Transpositions(transpositions bool) *FuzzyQuery {\n\tq.transpositions = &transpositions\n\treturn q\n}\n\nfunc (q *FuzzyQuery) Rewrite(rewrite string) *FuzzyQuery {\n\tq.rewrite = rewrite\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched filters per hit.\nfunc (q *FuzzyQuery) QueryName(queryName string) *FuzzyQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *FuzzyQuery) Source() (interface{}, error) {\n\t// {\n\t//\t\"fuzzy\" : {\n\t//\t\t\"user\" : {\n\t//      \"value\" : \"ki\",\n\t//      \"boost\" : 1.0,\n\t//      \"fuzziness\" : 2,\n\t//      \"prefix_length\" : 0,\n\t//      \"max_expansions\" : 100\n\t//    }\n\t// }\n\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"fuzzy\"] = query\n\n\tfq := make(map[string]interface{})\n\tquery[q.name] = fq\n\n\tfq[\"value\"] = q.value\n\n\tif q.boost != nil {\n\t\tfq[\"boost\"] = *q.boost\n\t}\n\tif q.transpositions != nil {\n\t\tfq[\"transpositions\"] = *q.transpositions\n\t}\n\tif q.fuzziness != nil {\n\t\tfq[\"fuzziness\"] = q.fuzziness\n\t}\n\tif q.prefixLength != nil {\n\t\tfq[\"prefix_length\"] = *q.prefixLength\n\t}\n\tif q.maxExpansions != nil {\n\t\tfq[\"max_expansions\"] = *q.maxExpansions\n\t}\n\tif q.rewrite != \"\" {\n\t\tfq[\"rewrite\"] = q.rewrite\n\t}\n\tif q.queryName != \"\" {\n\t\tfq[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_fuzzy_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestFuzzyQuery(t *testing.T) {\n\tq := NewFuzzyQuery(\"user\", \"ki\").Boost(1.5).Fuzziness(2).PrefixLength(0).MaxExpansions(100)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"fuzzy\":{\"user\":{\"boost\":1.5,\"fuzziness\":2,\"max_expansions\":100,\"prefix_length\":0,\"value\":\"ki\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_geo_bounding_box.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// GeoBoundingBoxQuery allows to filter hits based on a point location using\n// a bounding box.\n//\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-geo-bounding-box-query.html\ntype GeoBoundingBoxQuery struct {\n\tname             string\n\ttopLeft          interface{} // can be a GeoPoint, a GeoHash (string), or a lat/lon pair as float64\n\ttopRight         interface{}\n\tbottomRight      interface{} // can be a GeoPoint, a GeoHash (string), or a lat/lon pair as float64\n\tbottomLeft       interface{}\n\twkt              interface{}\n\ttyp              string\n\tvalidationMethod string\n\tignoreUnmapped   *bool\n\tqueryName        string\n}\n\n// NewGeoBoundingBoxQuery creates and initializes a new GeoBoundingBoxQuery.\nfunc NewGeoBoundingBoxQuery(name string) *GeoBoundingBoxQuery {\n\treturn &GeoBoundingBoxQuery{\n\t\tname: name,\n\t}\n}\n\n// TopLeft position from longitude (left) and latitude (top).\nfunc (q *GeoBoundingBoxQuery) TopLeft(top, left float64) *GeoBoundingBoxQuery {\n\tq.topLeft = []float64{left, top}\n\treturn q\n}\n\n// TopLeftFromGeoPoint from a GeoPoint.\nfunc (q *GeoBoundingBoxQuery) TopLeftFromGeoPoint(point *GeoPoint) *GeoBoundingBoxQuery {\n\treturn q.TopLeft(point.Lat, point.Lon)\n}\n\n// TopLeftFromGeoHash from a Geo hash.\nfunc (q *GeoBoundingBoxQuery) TopLeftFromGeoHash(topLeft string) *GeoBoundingBoxQuery {\n\tq.topLeft = topLeft\n\treturn q\n}\n\n// BottomRight position from longitude (right) and latitude (bottom).\nfunc (q *GeoBoundingBoxQuery) BottomRight(bottom, right float64) *GeoBoundingBoxQuery {\n\tq.bottomRight = []float64{right, bottom}\n\treturn q\n}\n\n// BottomRightFromGeoPoint from a GeoPoint.\nfunc (q *GeoBoundingBoxQuery) BottomRightFromGeoPoint(point *GeoPoint) *GeoBoundingBoxQuery {\n\treturn q.BottomRight(point.Lat, point.Lon)\n}\n\n// BottomRightFromGeoHash from a Geo hash.\nfunc (q *GeoBoundingBoxQuery) BottomRightFromGeoHash(bottomRight string) *GeoBoundingBoxQuery {\n\tq.bottomRight = bottomRight\n\treturn q\n}\n\n// BottomLeft position from longitude (left) and latitude (bottom).\nfunc (q *GeoBoundingBoxQuery) BottomLeft(bottom, left float64) *GeoBoundingBoxQuery {\n\tq.bottomLeft = []float64{bottom, left}\n\treturn q\n}\n\n// BottomLeftFromGeoPoint from a GeoPoint.\nfunc (q *GeoBoundingBoxQuery) BottomLeftFromGeoPoint(point *GeoPoint) *GeoBoundingBoxQuery {\n\treturn q.BottomLeft(point.Lat, point.Lon)\n}\n\n// BottomLeftFromGeoHash from a Geo hash.\nfunc (q *GeoBoundingBoxQuery) BottomLeftFromGeoHash(bottomLeft string) *GeoBoundingBoxQuery {\n\tq.bottomLeft = bottomLeft\n\treturn q\n}\n\n// TopRight position from longitude (right) and latitude (top).\nfunc (q *GeoBoundingBoxQuery) TopRight(top, right float64) *GeoBoundingBoxQuery {\n\tq.topRight = []float64{right, top}\n\treturn q\n}\n\n// TopRightFromGeoPoint from a GeoPoint.\nfunc (q *GeoBoundingBoxQuery) TopRightFromGeoPoint(point *GeoPoint) *GeoBoundingBoxQuery {\n\treturn q.TopRight(point.Lat, point.Lon)\n}\n\n// TopRightFromGeoHash from a Geo hash.\nfunc (q *GeoBoundingBoxQuery) TopRightFromGeoHash(topRight string) *GeoBoundingBoxQuery {\n\tq.topRight = topRight\n\treturn q\n}\n\n// WKT initializes the bounding box from Well-Known Text (WKT),\n// e.g. \"BBOX (-74.1, -71.12, 40.73, 40.01)\".\nfunc (q *GeoBoundingBoxQuery) WKT(wkt interface{}) *GeoBoundingBoxQuery {\n\tq.wkt = wkt\n\treturn q\n}\n\n// Type sets the type of executing the geo bounding box. It can be either\n// memory or indexed. It defaults to memory.\nfunc (q *GeoBoundingBoxQuery) Type(typ string) *GeoBoundingBoxQuery {\n\tq.typ = typ\n\treturn q\n}\n\n// ValidationMethod accepts IGNORE_MALFORMED, COERCE, and STRICT (default).\n// IGNORE_MALFORMED accepts geo points with invalid lat/lon.\n// COERCE tries to infer the correct lat/lon.\nfunc (q *GeoBoundingBoxQuery) ValidationMethod(method string) *GeoBoundingBoxQuery {\n\tq.validationMethod = method\n\treturn q\n}\n\n// IgnoreUnmapped indicates whether to ignore unmapped fields (and run a\n// MatchNoDocsQuery in place of this).\nfunc (q *GeoBoundingBoxQuery) IgnoreUnmapped(ignoreUnmapped bool) *GeoBoundingBoxQuery {\n\tq.ignoreUnmapped = &ignoreUnmapped\n\treturn q\n}\n\n// QueryName gives the query a name. It is used for caching.\nfunc (q *GeoBoundingBoxQuery) QueryName(queryName string) *GeoBoundingBoxQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *GeoBoundingBoxQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"geo_bounding_box\" : {\n\t//     ...\n\t//   }\n\t// }\n\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"geo_bounding_box\"] = params\n\n\tbox := make(map[string]interface{})\n\tif q.wkt != nil {\n\t\tbox[\"wkt\"] = q.wkt\n\t} else {\n\t\tif q.topLeft != nil {\n\t\t\tbox[\"top_left\"] = q.topLeft\n\t\t}\n\t\tif q.topRight != nil {\n\t\t\tbox[\"top_right\"] = q.topRight\n\t\t}\n\t\tif q.bottomLeft != nil {\n\t\t\tbox[\"bottom_left\"] = q.bottomLeft\n\t\t}\n\t\tif q.bottomRight != nil {\n\t\t\tbox[\"bottom_right\"] = q.bottomRight\n\t\t}\n\t}\n\tparams[q.name] = box\n\n\tif q.typ != \"\" {\n\t\tparams[\"type\"] = q.typ\n\t}\n\tif q.validationMethod != \"\" {\n\t\tparams[\"validation_method\"] = q.validationMethod\n\t}\n\tif q.ignoreUnmapped != nil {\n\t\tparams[\"ignore_unmapped\"] = *q.ignoreUnmapped\n\t}\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_geo_bounding_box_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGeoBoundingBoxQuery(t *testing.T) {\n\tq := NewGeoBoundingBoxQuery(\"pin.location\")\n\tq = q.TopLeft(40.73, -74.1)\n\tq = q.BottomRight(40.01, -71.12)\n\tq = q.Type(\"memory\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_bounding_box\":{\"pin.location\":{\"bottom_right\":[-71.12,40.01],\"top_left\":[-74.1,40.73]},\"type\":\"memory\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoBoundingBoxQueryWithGeoPoint(t *testing.T) {\n\tq := NewGeoBoundingBoxQuery(\"pin.location\")\n\tq = q.TopLeftFromGeoPoint(GeoPointFromLatLon(40.73, -74.1))\n\tq = q.BottomRightFromGeoPoint(GeoPointFromLatLon(40.01, -71.12))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_bounding_box\":{\"pin.location\":{\"bottom_right\":[-71.12,40.01],\"top_left\":[-74.1,40.73]}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoBoundingBoxQueryWithGeoHash(t *testing.T) {\n\tq := NewGeoBoundingBoxQuery(\"pin.location\")\n\tq = q.TopLeftFromGeoHash(\"dr5r9ydj2y73\")\n\tq = q.BottomRightFromGeoHash(\"drj7teegpus6\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_bounding_box\":{\"pin.location\":{\"bottom_right\":\"drj7teegpus6\",\"top_left\":\"dr5r9ydj2y73\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoBoundingBoxQueryWithWKT(t *testing.T) {\n\tq := NewGeoBoundingBoxQuery(\"pin.location\")\n\tq = q.WKT(\"BBOX (-74.1, -71.12, 40.73, 40.01)\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_bounding_box\":{\"pin.location\":{\"wkt\":\"BBOX (-74.1, -71.12, 40.73, 40.01)\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoBoundingBoxQueryWithMixed(t *testing.T) {\n\tq := NewGeoBoundingBoxQuery(\"pin.location\")\n\tq = q.TopLeftFromGeoPoint(GeoPointFromLatLon(40.73, -74.1))\n\tq = q.BottomRightFromGeoHash(\"drj7teegpus6\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_bounding_box\":{\"pin.location\":{\"bottom_right\":\"drj7teegpus6\",\"top_left\":[-74.1,40.73]}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoBoundingBoxQueryWithParameters(t *testing.T) {\n\tq := NewGeoBoundingBoxQuery(\"pin.location\")\n\tq = q.TopLeftFromGeoHash(\"dr5r9ydj2y73\")\n\tq = q.BottomRightFromGeoHash(\"drj7teegpus6\")\n\tq = q.ValidationMethod(\"IGNORE_MALFORMED\")\n\tq = q.IgnoreUnmapped((true))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_bounding_box\":{\"ignore_unmapped\":true,\"pin.location\":{\"bottom_right\":\"drj7teegpus6\",\"top_left\":\"dr5r9ydj2y73\"},\"validation_method\":\"IGNORE_MALFORMED\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_geo_distance.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// GeoDistanceQuery filters documents that include only hits that exists\n// within a specific distance from a geo point.\n//\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-geo-distance-query.html\ntype GeoDistanceQuery struct {\n\tname         string\n\tdistance     string\n\tlat          float64\n\tlon          float64\n\tgeohash      string\n\tdistanceType string\n\tqueryName    string\n}\n\n// NewGeoDistanceQuery creates and initializes a new GeoDistanceQuery.\nfunc NewGeoDistanceQuery(name string) *GeoDistanceQuery {\n\treturn &GeoDistanceQuery{name: name}\n}\n\nfunc (q *GeoDistanceQuery) GeoPoint(point *GeoPoint) *GeoDistanceQuery {\n\tq.lat = point.Lat\n\tq.lon = point.Lon\n\treturn q\n}\n\nfunc (q *GeoDistanceQuery) Point(lat, lon float64) *GeoDistanceQuery {\n\tq.lat = lat\n\tq.lon = lon\n\treturn q\n}\n\nfunc (q *GeoDistanceQuery) Lat(lat float64) *GeoDistanceQuery {\n\tq.lat = lat\n\treturn q\n}\n\nfunc (q *GeoDistanceQuery) Lon(lon float64) *GeoDistanceQuery {\n\tq.lon = lon\n\treturn q\n}\n\nfunc (q *GeoDistanceQuery) GeoHash(geohash string) *GeoDistanceQuery {\n\tq.geohash = geohash\n\treturn q\n}\n\nfunc (q *GeoDistanceQuery) Distance(distance string) *GeoDistanceQuery {\n\tq.distance = distance\n\treturn q\n}\n\nfunc (q *GeoDistanceQuery) DistanceType(distanceType string) *GeoDistanceQuery {\n\tq.distanceType = distanceType\n\treturn q\n}\n\nfunc (q *GeoDistanceQuery) QueryName(queryName string) *GeoDistanceQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *GeoDistanceQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"geo_distance\" : {\n\t//       \"distance\" : \"200km\",\n\t//       \"pin.location\" : {\n\t//           \"lat\" : 40,\n\t//           \"lon\" : -70\n\t//       }\n\t//   }\n\t// }\n\n\tsource := make(map[string]interface{})\n\n\tparams := make(map[string]interface{})\n\n\tif q.geohash != \"\" {\n\t\tparams[q.name] = q.geohash\n\t} else {\n\t\tlocation := make(map[string]interface{})\n\t\tlocation[\"lat\"] = q.lat\n\t\tlocation[\"lon\"] = q.lon\n\t\tparams[q.name] = location\n\t}\n\n\tif q.distance != \"\" {\n\t\tparams[\"distance\"] = q.distance\n\t}\n\tif q.distanceType != \"\" {\n\t\tparams[\"distance_type\"] = q.distanceType\n\t}\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\n\tsource[\"geo_distance\"] = params\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_geo_distance_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGeoDistanceQuery(t *testing.T) {\n\tq := NewGeoDistanceQuery(\"pin.location\")\n\tq = q.Lat(40)\n\tq = q.Lon(-70)\n\tq = q.Distance(\"200km\")\n\tq = q.DistanceType(\"plane\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_distance\":{\"distance\":\"200km\",\"distance_type\":\"plane\",\"pin.location\":{\"lat\":40,\"lon\":-70}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoDistanceQueryWithGeoPoint(t *testing.T) {\n\tq := NewGeoDistanceQuery(\"pin.location\")\n\tq = q.GeoPoint(GeoPointFromLatLon(40, -70))\n\tq = q.Distance(\"200km\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_distance\":{\"distance\":\"200km\",\"pin.location\":{\"lat\":40,\"lon\":-70}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoDistanceQueryWithGeoHash(t *testing.T) {\n\tq := NewGeoDistanceQuery(\"pin.location\")\n\tq = q.GeoHash(\"drm3btev3e86\")\n\tq = q.Distance(\"12km\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_distance\":{\"distance\":\"12km\",\"pin.location\":\"drm3btev3e86\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_geo_polygon.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// GeoPolygonQuery allows to include hits that only fall within a polygon of points.\n//\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-geo-polygon-query.html\ntype GeoPolygonQuery struct {\n\tname      string\n\tpoints    []*GeoPoint\n\tqueryName string\n}\n\n// NewGeoPolygonQuery creates and initializes a new GeoPolygonQuery.\nfunc NewGeoPolygonQuery(name string) *GeoPolygonQuery {\n\treturn &GeoPolygonQuery{\n\t\tname:   name,\n\t\tpoints: make([]*GeoPoint, 0),\n\t}\n}\n\n// AddPoint adds a point from latitude and longitude.\nfunc (q *GeoPolygonQuery) AddPoint(lat, lon float64) *GeoPolygonQuery {\n\tq.points = append(q.points, GeoPointFromLatLon(lat, lon))\n\treturn q\n}\n\n// AddGeoPoint adds a GeoPoint.\nfunc (q *GeoPolygonQuery) AddGeoPoint(point *GeoPoint) *GeoPolygonQuery {\n\tq.points = append(q.points, point)\n\treturn q\n}\n\nfunc (q *GeoPolygonQuery) QueryName(queryName string) *GeoPolygonQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *GeoPolygonQuery) Source() (interface{}, error) {\n\t// \"geo_polygon\" : {\n\t//  \t\"person.location\" : {\n\t//         \"points\" : [\n\t//             {\"lat\" : 40, \"lon\" : -70},\n\t//             {\"lat\" : 30, \"lon\" : -80},\n\t//             {\"lat\" : 20, \"lon\" : -90}\n\t//         ]\n\t//     }\n\t// }\n\tsource := make(map[string]interface{})\n\n\tparams := make(map[string]interface{})\n\tsource[\"geo_polygon\"] = params\n\n\tpolygon := make(map[string]interface{})\n\tparams[q.name] = polygon\n\n\tvar points []interface{}\n\tfor _, point := range q.points {\n\t\tpoints = append(points, point.Source())\n\t}\n\tpolygon[\"points\"] = points\n\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_geo_polygon_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestGeoPolygonQuery(t *testing.T) {\n\tq := NewGeoPolygonQuery(\"person.location\")\n\tq = q.AddPoint(40, -70)\n\tq = q.AddPoint(30, -80)\n\tpoint, err := GeoPointFromString(\"20,-90\")\n\tif err != nil {\n\t\tt.Fatalf(\"GeoPointFromString failed: %v\", err)\n\t}\n\tq = q.AddGeoPoint(point)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_polygon\":{\"person.location\":{\"points\":[{\"lat\":40,\"lon\":-70},{\"lat\":30,\"lon\":-80},{\"lat\":20,\"lon\":-90}]}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoPolygonQueryFromGeoPoints(t *testing.T) {\n\tq := NewGeoPolygonQuery(\"person.location\")\n\tq = q.AddGeoPoint(&GeoPoint{Lat: 40, Lon: -70})\n\tq = q.AddGeoPoint(GeoPointFromLatLon(30, -80))\n\tpoint, err := GeoPointFromString(\"20,-90\")\n\tif err != nil {\n\t\tt.Fatalf(\"GeoPointFromString failed: %v\", err)\n\t}\n\tq = q.AddGeoPoint(point)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"geo_polygon\":{\"person.location\":{\"points\":[{\"lat\":40,\"lon\":-70},{\"lat\":30,\"lon\":-80},{\"lat\":20,\"lon\":-90}]}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_has_child.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// HasChildQuery accepts a query and the child type to run against, and results\n// in parent documents that have child docs matching the query.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-has-child-query.html\ntype HasChildQuery struct {\n\tquery              Query\n\tchildType          string\n\tboost              *float64\n\tscoreMode          string\n\tminChildren        *int\n\tmaxChildren        *int\n\tshortCircuitCutoff *int\n\tqueryName          string\n\tinnerHit           *InnerHit\n}\n\n// NewHasChildQuery creates and initializes a new has_child query.\nfunc NewHasChildQuery(childType string, query Query) *HasChildQuery {\n\treturn &HasChildQuery{\n\t\tquery:     query,\n\t\tchildType: childType,\n\t}\n}\n\n// Boost sets the boost for this query.\nfunc (q *HasChildQuery) Boost(boost float64) *HasChildQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// ScoreMode defines how the scores from the matching child documents\n// are mapped into the parent document. Allowed values are: min, max,\n// avg, or none.\nfunc (q *HasChildQuery) ScoreMode(scoreMode string) *HasChildQuery {\n\tq.scoreMode = scoreMode\n\treturn q\n}\n\n// MinChildren defines the minimum number of children that are required\n// to match for the parent to be considered a match.\nfunc (q *HasChildQuery) MinChildren(minChildren int) *HasChildQuery {\n\tq.minChildren = &minChildren\n\treturn q\n}\n\n// MaxChildren defines the maximum number of children that are required\n// to match for the parent to be considered a match.\nfunc (q *HasChildQuery) MaxChildren(maxChildren int) *HasChildQuery {\n\tq.maxChildren = &maxChildren\n\treturn q\n}\n\n// ShortCircuitCutoff configures what cut off point only to evaluate\n// parent documents that contain the matching parent id terms instead\n// of evaluating all parent docs.\nfunc (q *HasChildQuery) ShortCircuitCutoff(shortCircuitCutoff int) *HasChildQuery {\n\tq.shortCircuitCutoff = &shortCircuitCutoff\n\treturn q\n}\n\n// QueryName specifies the query name for the filter that can be used when\n// searching for matched filters per hit.\nfunc (q *HasChildQuery) QueryName(queryName string) *HasChildQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// InnerHit sets the inner hit definition in the scope of this query and\n// reusing the defined type and query.\nfunc (q *HasChildQuery) InnerHit(innerHit *InnerHit) *HasChildQuery {\n\tq.innerHit = innerHit\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *HasChildQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"has_child\" : {\n\t//       \"type\" : \"blog_tag\",\n\t//       \"score_mode\" : \"min\",\n\t//       \"query\" : {\n\t//           \"term\" : {\n\t//               \"tag\" : \"something\"\n\t//           }\n\t//       }\n\t//   }\n\t// }\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"has_child\"] = query\n\n\tsrc, err := q.query.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tquery[\"query\"] = src\n\tquery[\"type\"] = q.childType\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.scoreMode != \"\" {\n\t\tquery[\"score_mode\"] = q.scoreMode\n\t}\n\tif q.minChildren != nil {\n\t\tquery[\"min_children\"] = *q.minChildren\n\t}\n\tif q.maxChildren != nil {\n\t\tquery[\"max_children\"] = *q.maxChildren\n\t}\n\tif q.shortCircuitCutoff != nil {\n\t\tquery[\"short_circuit_cutoff\"] = *q.shortCircuitCutoff\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\tif q.innerHit != nil {\n\t\tsrc, err := q.innerHit.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tquery[\"inner_hits\"] = src\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_has_child_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestHasChildQuery(t *testing.T) {\n\tq := NewHasChildQuery(\"blog_tag\", NewTermQuery(\"tag\", \"something\")).ScoreMode(\"min\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"has_child\":{\"query\":{\"term\":{\"tag\":\"something\"}},\"score_mode\":\"min\",\"type\":\"blog_tag\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestHasChildQueryWithInnerHit(t *testing.T) {\n\tq := NewHasChildQuery(\"blog_tag\", NewTermQuery(\"tag\", \"something\"))\n\tq = q.InnerHit(NewInnerHit().Name(\"comments\"))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"has_child\":{\"inner_hits\":{\"name\":\"comments\"},\"query\":{\"term\":{\"tag\":\"something\"}},\"type\":\"blog_tag\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_has_parent.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// HasParentQuery accepts a query and a parent type. The query is executed\n// in the parent document space which is specified by the parent type.\n// This query returns child documents which associated parents have matched.\n// For the rest has_parent query has the same options and works in the\n// same manner as has_child query.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-has-parent-query.html\ntype HasParentQuery struct {\n\tquery          Query\n\tparentType     string\n\tboost          *float64\n\tscore          *bool\n\tqueryName      string\n\tinnerHit       *InnerHit\n\tignoreUnmapped *bool\n}\n\n// NewHasParentQuery creates and initializes a new has_parent query.\nfunc NewHasParentQuery(parentType string, query Query) *HasParentQuery {\n\treturn &HasParentQuery{\n\t\tquery:      query,\n\t\tparentType: parentType,\n\t}\n}\n\n// Boost sets the boost for this query.\nfunc (q *HasParentQuery) Boost(boost float64) *HasParentQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// Score defines if the parent score is mapped into the child documents.\nfunc (q *HasParentQuery) Score(score bool) *HasParentQuery {\n\tq.score = &score\n\treturn q\n}\n\n// QueryName specifies the query name for the filter that can be used when\n// searching for matched filters per hit.\nfunc (q *HasParentQuery) QueryName(queryName string) *HasParentQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// InnerHit sets the inner hit definition in the scope of this query and\n// reusing the defined type and query.\nfunc (q *HasParentQuery) InnerHit(innerHit *InnerHit) *HasParentQuery {\n\tq.innerHit = innerHit\n\treturn q\n}\n\n// IgnoreUnmapped specifies whether unmapped types should be ignored.\n// If set to false, the query failes when an unmapped type is found.\nfunc (q *HasParentQuery) IgnoreUnmapped(ignore bool) *HasParentQuery {\n\tq.ignoreUnmapped = &ignore\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *HasParentQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"has_parent\" : {\n\t//       \"parent_type\" : \"blog\",\n\t//       \"query\" : {\n\t//           \"term\" : {\n\t//               \"tag\" : \"something\"\n\t//           }\n\t//       }\n\t//   }\n\t// }\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"has_parent\"] = query\n\n\tsrc, err := q.query.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tquery[\"query\"] = src\n\tquery[\"parent_type\"] = q.parentType\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.score != nil {\n\t\tquery[\"score\"] = *q.score\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\tif q.innerHit != nil {\n\t\tsrc, err := q.innerHit.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tquery[\"inner_hits\"] = src\n\t}\n\tif q.ignoreUnmapped != nil {\n\t\tquery[\"ignore_unmapped\"] = *q.ignoreUnmapped\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_has_parent_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestHasParentQueryTest(t *testing.T) {\n\tq := NewHasParentQuery(\"blog\", NewTermQuery(\"tag\", \"something\")).Score(true)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"has_parent\":{\"parent_type\":\"blog\",\"query\":{\"term\":{\"tag\":\"something\"}},\"score\":true}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_ids.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// IdsQuery filters documents that only have the provided ids.\n// Note, this query uses the _uid field.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.6/query-dsl-ids-query.html\ntype IdsQuery struct {\n\ttypes     []string\n\tvalues    []string\n\tboost     *float64\n\tqueryName string\n}\n\n// NewIdsQuery creates and initializes a new ids query.\n//\n// Notice that types are in the process of being removed.\n// You should filter on a field instead.\nfunc NewIdsQuery(types ...string) *IdsQuery {\n\treturn &IdsQuery{\n\t\ttypes:  types,\n\t\tvalues: make([]string, 0),\n\t}\n}\n\n// Ids adds ids to the filter.\nfunc (q *IdsQuery) Ids(ids ...string) *IdsQuery {\n\tq.values = append(q.values, ids...)\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *IdsQuery) Boost(boost float64) *IdsQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter.\nfunc (q *IdsQuery) QueryName(queryName string) *IdsQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *IdsQuery) Source() (interface{}, error) {\n\t// {\n\t//\t\"ids\" : {\n\t//\t\t\"type\" : \"my_type\",\n\t//\t\t\"values\" : [\"1\", \"4\", \"100\"]\n\t//\t}\n\t// }\n\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"ids\"] = query\n\n\t// type(s)\n\tif len(q.types) == 1 {\n\t\tquery[\"type\"] = q.types[0]\n\t} else if len(q.types) > 1 {\n\t\tquery[\"types\"] = q.types\n\t}\n\n\t// values\n\tquery[\"values\"] = q.values\n\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_ids_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestIdsQuery(t *testing.T) {\n\tq := NewIdsQuery(\"my_type\").Ids(\"1\", \"4\", \"100\").Boost(10.5).QueryName(\"my_query\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"ids\":{\"_name\":\"my_query\",\"boost\":10.5,\"type\":\"my_type\",\"values\":[\"1\",\"4\",\"100\"]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_interval.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// IntervalQueryRule represents the generic matching interval rule interface.\n// Interval Rule is actually just a Query, but may be used only inside\n// IntervalQuery. An extra method is added just to shield its\n// implementations (*Rule objects) from other query objects.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-intervals-query.html\n// for details.\ntype IntervalQueryRule interface {\n\tQuery\n\n\t// isIntervalQueryRule is never actually called, and is used just for Rule to\n\t// differ from standard Query.\n\tisIntervalQueryRule() bool\n}\n\n// IntervalQuery returns documents based on the order and proximity of matching terms.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-intervals-query.html\ntype IntervalQuery struct {\n\tfield string\n\trule  IntervalQueryRule\n}\n\n// NewIntervalQuery creates and initializes a new IntervalQuery.\nfunc NewIntervalQuery(field string, rule IntervalQueryRule) *IntervalQuery {\n\treturn &IntervalQuery{field: field, rule: rule}\n}\n\n// Source returns JSON for the function score query.\nfunc (q *IntervalQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"intervals\" : { ... }\n\t// }\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"intervals\"] = params\n\n\tsrc, err := q.rule.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tparams[q.field] = src\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_interval_filter.go",
    "content": "package elastic\n\nvar (\n\t_ IntervalQueryRule = (*IntervalQueryFilter)(nil)\n)\n\n// IntervalQueryFilter specifies filters used in some\n// IntervalQueryRule implementations, e.g. IntervalQueryRuleAllOf.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-intervals-query.html#interval_filter\n// for details.\ntype IntervalQueryFilter struct {\n\tafter          IntervalQueryRule\n\tbefore         IntervalQueryRule\n\tcontainedBy    IntervalQueryRule\n\tcontaining     IntervalQueryRule\n\toverlapping    IntervalQueryRule\n\tnotContainedBy IntervalQueryRule\n\tnotContaining  IntervalQueryRule\n\tnotOverlapping IntervalQueryRule\n\tscript         *Script\n}\n\n// NewIntervalQueryFilter initializes and creates a new\n// IntervalQueryFilter.\nfunc NewIntervalQueryFilter() *IntervalQueryFilter {\n\treturn &IntervalQueryFilter{}\n}\n\n// After specifies the query to be used to return intervals that follow\n// an interval from the filter rule.\nfunc (r *IntervalQueryFilter) After(after IntervalQueryRule) *IntervalQueryFilter {\n\tr.after = after\n\treturn r\n}\n\n// Before specifies the query to be used to return intervals that occur\n// before an interval from the filter rule.\nfunc (r *IntervalQueryFilter) Before(before IntervalQueryRule) *IntervalQueryFilter {\n\tr.before = before\n\treturn r\n}\n\n// ContainedBy specifies the query to be used to return intervals contained\n// by an interval from the filter rule.\nfunc (r *IntervalQueryFilter) ContainedBy(containedBy IntervalQueryRule) *IntervalQueryFilter {\n\tr.containedBy = containedBy\n\treturn r\n}\n\n// Containing specifies the query to be used to return intervals that contain an\n// interval from the filter rule.\nfunc (r *IntervalQueryFilter) Containing(containing IntervalQueryRule) *IntervalQueryFilter {\n\tr.containing = containing\n\treturn r\n}\n\n// Overlapping specifies the query to be used to return intervals that overlap\n// with an interval from the filter rule.\nfunc (r *IntervalQueryFilter) Overlapping(overlapping IntervalQueryRule) *IntervalQueryFilter {\n\tr.overlapping = overlapping\n\treturn r\n}\n\n// NotContainedBy specifies the query to be used to return intervals that are NOT\n// contained by an interval from the filter rule.\nfunc (r *IntervalQueryFilter) NotContainedBy(notContainedBy IntervalQueryRule) *IntervalQueryFilter {\n\tr.notContainedBy = notContainedBy\n\treturn r\n}\n\n// NotContaining specifies the query to be used to return intervals that do NOT\n// contain an interval from the filter rule.\nfunc (r *IntervalQueryFilter) NotContaining(notContaining IntervalQueryRule) *IntervalQueryFilter {\n\tr.notContaining = notContaining\n\treturn r\n}\n\n// NotOverlapping specifies the query to be used to return intervals that do NOT\n// overlap with an interval from the filter rule.\nfunc (r *IntervalQueryFilter) NotOverlapping(notOverlapping IntervalQueryRule) *IntervalQueryFilter {\n\tr.notOverlapping = notOverlapping\n\treturn r\n}\n\n// Script allows a script to be used to return matching documents. The script\n// must return a boolean value, true or false.\nfunc (r *IntervalQueryFilter) Script(script *Script) *IntervalQueryFilter {\n\tr.script = script\n\treturn r\n}\n\n// Source returns JSON for the function score query.\nfunc (r *IntervalQueryFilter) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tif r.before != nil {\n\t\tsrc, err := r.before.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"before\"] = src\n\t}\n\n\tif r.after != nil {\n\t\tsrc, err := r.after.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"after\"] = src\n\t}\n\n\tif r.containedBy != nil {\n\t\tsrc, err := r.containedBy.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"contained_by\"] = src\n\t}\n\n\tif r.containing != nil {\n\t\tsrc, err := r.containing.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"containing\"] = src\n\t}\n\n\tif r.overlapping != nil {\n\t\tsrc, err := r.overlapping.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"overlapping\"] = src\n\t}\n\n\tif r.notContainedBy != nil {\n\t\tsrc, err := r.notContainedBy.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"not_contained_by\"] = src\n\t}\n\n\tif r.notContaining != nil {\n\t\tsrc, err := r.notContaining.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"not_containing\"] = src\n\t}\n\n\tif r.notOverlapping != nil {\n\t\tsrc, err := r.notOverlapping.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"not_overlapping\"] = src\n\t}\n\n\tif r.script != nil {\n\t\tsrc, err := r.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"script\"] = src\n\t}\n\n\treturn source, nil\n}\n\n// isIntervalQueryRule implements the marker interface.\nfunc (r *IntervalQueryFilter) isIntervalQueryRule() bool {\n\treturn true\n}\n"
  },
  {
    "path": "search_queries_interval_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestIntervalQuery_Integration(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\tt.Run(\"Match\", func(t *testing.T) {\n\t\ttestIntervalQueryMatch(client, t)\n\t})\n\tt.Run(\"Prefix\", func(t *testing.T) {\n\t\ttestIntervalQueryPrefix(client, t)\n\t})\n\tt.Run(\"Wildcard\", func(t *testing.T) {\n\t\ttestIntervalQueryWildcard(client, t)\n\t})\n\tt.Run(\"Fuzzy\", func(t *testing.T) {\n\t\ttestIntervalQueryFuzzy(client, t)\n\t})\n}\n\nfunc testIntervalQueryMatch(client *Client, t *testing.T) {\n\tq := NewIntervalQuery(\n\t\t\"message\",\n\t\tNewIntervalQueryRuleAllOf(\n\t\t\tNewIntervalQueryRuleAnyOf(\n\t\t\t\tNewIntervalQueryRuleMatch(\"Golang\").Ordered(true),\n\t\t\t\tNewIntervalQueryRuleMatch(\"Cycling\").MaxGaps(0).Filter(\n\t\t\t\t\tNewIntervalQueryFilter().NotContaining(\n\t\t\t\t\t\tNewIntervalQueryRuleMatch(\"Hockey\"),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t).Ordered(true),\n\t)\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(q).\n\t\tSize(10).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(2); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 2; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc testIntervalQueryPrefix(client *Client, t *testing.T) {\n\tq := NewIntervalQuery(\n\t\t\"message\",\n\t\tNewIntervalQueryRuleAllOf(\n\t\t\tNewIntervalQueryRuleAnyOf(\n\t\t\t\tNewIntervalQueryRuleMatch(\"Golang\").Ordered(true),\n\t\t\t\tNewIntervalQueryRuleMatch(\"Cycling\").MaxGaps(0).Filter(\n\t\t\t\t\tNewIntervalQueryFilter().NotContaining(\n\t\t\t\t\t\tNewIntervalQueryRulePrefix(\"Hockey\"),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t).Ordered(true),\n\t)\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(q).\n\t\tSize(10).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(2); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 2; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc testIntervalQueryWildcard(client *Client, t *testing.T) {\n\tq := NewIntervalQuery(\n\t\t\"message\",\n\t\tNewIntervalQueryRuleAllOf(\n\t\t\tNewIntervalQueryRuleAnyOf(\n\t\t\t\tNewIntervalQueryRuleMatch(\"Golang\").Ordered(true),\n\t\t\t\tNewIntervalQueryRuleMatch(\"Cycling\").MaxGaps(0).Filter(\n\t\t\t\t\tNewIntervalQueryFilter().NotContaining(\n\t\t\t\t\t\tNewIntervalQueryRuleWildcard(\"Hockey*\"),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t).Ordered(true),\n\t)\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(q).\n\t\tSize(10).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(2); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 2; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc testIntervalQueryFuzzy(client *Client, t *testing.T) {\n\tq := NewIntervalQuery(\n\t\t\"message\",\n\t\tNewIntervalQueryRuleAllOf(\n\t\t\tNewIntervalQueryRuleAnyOf(\n\t\t\t\tNewIntervalQueryRuleMatch(\"Golang\").Ordered(true),\n\t\t\t\tNewIntervalQueryRuleMatch(\"Cycling\").MaxGaps(0).Filter(\n\t\t\t\t\tNewIntervalQueryFilter().NotContaining(\n\t\t\t\t\t\tNewIntervalQueryRuleFuzzy(\"Hocky\").Fuzziness(\"auto\"),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\t).Ordered(true),\n\t)\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(q).\n\t\tSize(10).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(2); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 2; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "search_queries_interval_rules_all_of.go",
    "content": "package elastic\n\nvar (\n\t_ IntervalQueryRule = (*IntervalQueryRuleAllOf)(nil)\n)\n\n// IntervalQueryRuleAllOf is an implementation of IntervalQueryRule.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-intervals-query.html#intervals-all_of\n// for details.\ntype IntervalQueryRuleAllOf struct {\n\tintervals []IntervalQueryRule\n\tmaxGaps   *int\n\tordered   *bool\n\tfilter    *IntervalQueryFilter\n}\n\n// NewIntervalQueryRuleAllOf initializes and returns a new instance\n// of IntervalQueryRuleAllOf.\nfunc NewIntervalQueryRuleAllOf(intervals ...IntervalQueryRule) *IntervalQueryRuleAllOf {\n\treturn &IntervalQueryRuleAllOf{intervals: intervals}\n}\n\n// MaxGaps specifies the maximum number of positions between the matching\n// terms. Terms further apart than this are considered matches. Defaults to -1.\nfunc (r *IntervalQueryRuleAllOf) MaxGaps(maxGaps int) *IntervalQueryRuleAllOf {\n\tr.maxGaps = &maxGaps\n\treturn r\n}\n\n// Ordered, if true, indicates that matching terms must appear in their specified\n// order. Defaults to false.\nfunc (r *IntervalQueryRuleAllOf) Ordered(ordered bool) *IntervalQueryRuleAllOf {\n\tr.ordered = &ordered\n\treturn r\n}\n\n// Filter adds an additional interval filter.\nfunc (r *IntervalQueryRuleAllOf) Filter(filter *IntervalQueryFilter) *IntervalQueryRuleAllOf {\n\tr.filter = filter\n\treturn r\n}\n\n// Source returns JSON for the function score query.\nfunc (r *IntervalQueryRuleAllOf) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tintervalSources := make([]interface{}, 0)\n\tfor _, interval := range r.intervals {\n\t\tsrc, err := interval.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tintervalSources = append(intervalSources, src)\n\t}\n\tsource[\"intervals\"] = intervalSources\n\n\tif r.ordered != nil {\n\t\tsource[\"ordered\"] = *r.ordered\n\t}\n\tif r.maxGaps != nil {\n\t\tsource[\"max_gaps\"] = *r.maxGaps\n\t}\n\tif r.filter != nil {\n\t\tsrc, err := r.filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tsource[\"filter\"] = src\n\t}\n\n\treturn map[string]interface{}{\n\t\t\"all_of\": source,\n\t}, nil\n}\n\n// isIntervalQueryRule implements the marker interface.\nfunc (r *IntervalQueryRuleAllOf) isIntervalQueryRule() bool {\n\treturn true\n}\n"
  },
  {
    "path": "search_queries_interval_rules_any_of.go",
    "content": "package elastic\n\nvar (\n\t_ IntervalQueryRule = (*IntervalQueryRuleAnyOf)(nil)\n)\n\n// IntervalQueryRuleAnyOf is an implementation of IntervalQueryRule.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-intervals-query.html#intervals-any_of\n// for details.\ntype IntervalQueryRuleAnyOf struct {\n\tintervals []IntervalQueryRule\n\tfilter    *IntervalQueryFilter\n}\n\n// NewIntervalQueryRuleAnyOf initializes and returns a new instance\n// of IntervalQueryRuleAnyOf.\nfunc NewIntervalQueryRuleAnyOf(intervals ...IntervalQueryRule) *IntervalQueryRuleAnyOf {\n\treturn &IntervalQueryRuleAnyOf{intervals: intervals}\n}\n\n// Filter adds an additional interval filter.\nfunc (r *IntervalQueryRuleAnyOf) Filter(filter *IntervalQueryFilter) *IntervalQueryRuleAnyOf {\n\tr.filter = filter\n\treturn r\n}\n\n// Source returns JSON for the function score query.\nfunc (r *IntervalQueryRuleAnyOf) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tvar intervalSources []interface{}\n\tfor _, interval := range r.intervals {\n\t\tsrc, err := interval.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tintervalSources = append(intervalSources, src)\n\t}\n\tsource[\"intervals\"] = intervalSources\n\n\tif r.filter != nil {\n\t\tsrc, err := r.filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tsource[\"filter\"] = src\n\t}\n\n\treturn map[string]interface{}{\n\t\t\"any_of\": source,\n\t}, nil\n}\n\n// isIntervalQueryRule implements the marker interface.\nfunc (r *IntervalQueryRuleAnyOf) isIntervalQueryRule() bool {\n\treturn true\n}\n"
  },
  {
    "path": "search_queries_interval_rules_fuzzy.go",
    "content": "package elastic\n\nvar (\n\t_ IntervalQueryRule = (*IntervalQueryRuleFuzzy)(nil)\n)\n\n// IntervalQueryRuleFuzzy is an implementation of IntervalQueryRule.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.16/query-dsl-intervals-query.html#intervals-fuzzy\n// for details.\ntype IntervalQueryRuleFuzzy struct {\n\tterm           string\n\tprefixLength   *int\n\ttranspositions *bool\n\tfuzziness      interface{}\n\tanalyzer       string\n\tuseField       string\n}\n\n// NewIntervalQueryRuleFuzzy initializes and returns a new instance\n// of IntervalQueryRuleFuzzy.\nfunc NewIntervalQueryRuleFuzzy(term string) *IntervalQueryRuleFuzzy {\n\treturn &IntervalQueryRuleFuzzy{term: term}\n}\n\n// PrefixLength is the number of beginning characters left unchanged when\n// creating expansions. Defaults to 0.\nfunc (q *IntervalQueryRuleFuzzy) PrefixLength(prefixLength int) *IntervalQueryRuleFuzzy {\n\tq.prefixLength = &prefixLength\n\treturn q\n}\n\n// Fuzziness is the maximum edit distance allowed for matching.\n// It can be integers like 0, 1 or 2 as well as strings\n// like \"auto\", \"0..1\", \"1..4\" or \"0.0..1.0\". Defaults to \"auto\".\nfunc (q *IntervalQueryRuleFuzzy) Fuzziness(fuzziness interface{}) *IntervalQueryRuleFuzzy {\n\tq.fuzziness = fuzziness\n\treturn q\n}\n\n// Transpositions indicates whether edits include transpositions of two\n// adjacent characters (ab -> ba). Defaults to true.\nfunc (q *IntervalQueryRuleFuzzy) Transpositions(transpositions bool) *IntervalQueryRuleFuzzy {\n\tq.transpositions = &transpositions\n\treturn q\n}\n\n// Analyzer specifies the analyzer used to analyze terms in the query.\nfunc (r *IntervalQueryRuleFuzzy) Analyzer(analyzer string) *IntervalQueryRuleFuzzy {\n\tr.analyzer = analyzer\n\treturn r\n}\n\n// UseField, if specified, matches the intervals from this field rather than\n// the top-level field.\nfunc (r *IntervalQueryRuleFuzzy) UseField(useField string) *IntervalQueryRuleFuzzy {\n\tr.useField = useField\n\treturn r\n}\n\n// Source returns JSON for the function score query.\nfunc (r *IntervalQueryRuleFuzzy) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tsource[\"term\"] = r.term\n\n\tif r.prefixLength != nil {\n\t\tsource[\"prefix_length\"] = *r.prefixLength\n\t}\n\tif r.transpositions != nil {\n\t\tsource[\"transpositions\"] = *r.transpositions\n\t}\n\tif r.fuzziness != \"\" {\n\t\tsource[\"fuzziness\"] = r.fuzziness\n\t}\n\tif r.analyzer != \"\" {\n\t\tsource[\"analyzer\"] = r.analyzer\n\t}\n\tif r.useField != \"\" {\n\t\tsource[\"use_field\"] = r.useField\n\t}\n\n\treturn map[string]interface{}{\n\t\t\"fuzzy\": source,\n\t}, nil\n}\n\n// isIntervalQueryRule implements the marker interface.\nfunc (r *IntervalQueryRuleFuzzy) isIntervalQueryRule() bool {\n\treturn true\n}\n"
  },
  {
    "path": "search_queries_interval_rules_match.go",
    "content": "package elastic\n\nvar (\n\t_ IntervalQueryRule = (*IntervalQueryRuleMatch)(nil)\n)\n\n// IntervalQueryRuleMatch is an implementation of IntervalQueryRule.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-intervals-query.html#intervals-match\n// for details.\ntype IntervalQueryRuleMatch struct {\n\tquery    string\n\tmaxGaps  *int\n\tordered  *bool\n\tanalyzer string\n\tuseField string\n\tfilter   *IntervalQueryFilter\n}\n\n// NewIntervalQueryRuleMatch initializes and returns a new instance\n// of IntervalQueryRuleMatch.\nfunc NewIntervalQueryRuleMatch(query string) *IntervalQueryRuleMatch {\n\treturn &IntervalQueryRuleMatch{query: query}\n}\n\n// MaxGaps specifies the maximum number of positions between the matching\n// terms. Terms further apart than this are considered matches. Defaults to -1.\nfunc (r *IntervalQueryRuleMatch) MaxGaps(maxGaps int) *IntervalQueryRuleMatch {\n\tr.maxGaps = &maxGaps\n\treturn r\n}\n\n// Ordered, if true, indicates that matching terms must appear in their specified\n// order. Defaults to false.\nfunc (r *IntervalQueryRuleMatch) Ordered(ordered bool) *IntervalQueryRuleMatch {\n\tr.ordered = &ordered\n\treturn r\n}\n\n// Analyzer specifies the analyzer used to analyze terms in the query.\nfunc (r *IntervalQueryRuleMatch) Analyzer(analyzer string) *IntervalQueryRuleMatch {\n\tr.analyzer = analyzer\n\treturn r\n}\n\n// UseField, if specified, matches the intervals from this field rather than\n// the top-level field.\nfunc (r *IntervalQueryRuleMatch) UseField(useField string) *IntervalQueryRuleMatch {\n\tr.useField = useField\n\treturn r\n}\n\n// Filter adds an additional interval filter.\nfunc (r *IntervalQueryRuleMatch) Filter(filter *IntervalQueryFilter) *IntervalQueryRuleMatch {\n\tr.filter = filter\n\treturn r\n}\n\n// Source returns JSON for the function score query.\nfunc (r *IntervalQueryRuleMatch) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tsource[\"query\"] = r.query\n\n\tif r.ordered != nil {\n\t\tsource[\"ordered\"] = *r.ordered\n\t}\n\tif r.maxGaps != nil {\n\t\tsource[\"max_gaps\"] = *r.maxGaps\n\t}\n\tif r.analyzer != \"\" {\n\t\tsource[\"analyzer\"] = r.analyzer\n\t}\n\tif r.useField != \"\" {\n\t\tsource[\"use_field\"] = r.useField\n\t}\n\tif r.filter != nil {\n\t\tfilterRuleSource, err := r.filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tsource[\"filter\"] = filterRuleSource\n\t}\n\n\treturn map[string]interface{}{\n\t\t\"match\": source,\n\t}, nil\n}\n\n// isIntervalQueryRule implements the marker interface.\nfunc (r *IntervalQueryRuleMatch) isIntervalQueryRule() bool {\n\treturn true\n}\n"
  },
  {
    "path": "search_queries_interval_rules_prefix.go",
    "content": "package elastic\n\nvar (\n\t_ IntervalQueryRule = (*IntervalQueryRulePrefix)(nil)\n)\n\n// IntervalQueryRulePrefix is an implementation of IntervalQueryRule.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-intervals-query.html#intervals-prefix\n// for details.\ntype IntervalQueryRulePrefix struct {\n\tprefix   string\n\tanalyzer string\n\tuseField string\n}\n\n// NewIntervalQueryRulePrefix initializes and returns a new instance\n// of IntervalQueryRulePrefix.\nfunc NewIntervalQueryRulePrefix(prefix string) *IntervalQueryRulePrefix {\n\treturn &IntervalQueryRulePrefix{prefix: prefix}\n}\n\n// Analyzer specifies the analyzer used to analyze terms in the query.\nfunc (r *IntervalQueryRulePrefix) Analyzer(analyzer string) *IntervalQueryRulePrefix {\n\tr.analyzer = analyzer\n\treturn r\n}\n\n// UseField, if specified, matches the intervals from this field rather than\n// the top-level field.\nfunc (r *IntervalQueryRulePrefix) UseField(useField string) *IntervalQueryRulePrefix {\n\tr.useField = useField\n\treturn r\n}\n\n// Source returns JSON for the function score query.\nfunc (r *IntervalQueryRulePrefix) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tsource[\"prefix\"] = r.prefix\n\n\tif r.analyzer != \"\" {\n\t\tsource[\"analyzer\"] = r.analyzer\n\t}\n\tif r.useField != \"\" {\n\t\tsource[\"use_field\"] = r.useField\n\t}\n\n\treturn map[string]interface{}{\n\t\t\"prefix\": source,\n\t}, nil\n}\n\n// isIntervalQueryRule implements the marker interface.\nfunc (r *IntervalQueryRulePrefix) isIntervalQueryRule() bool {\n\treturn true\n}\n"
  },
  {
    "path": "search_queries_interval_rules_wildcard.go",
    "content": "package elastic\n\nvar (\n\t_ IntervalQueryRule = (*IntervalQueryRuleWildcard)(nil)\n)\n\n// IntervalQueryRuleWildcard is an implementation of IntervalQueryRule.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-intervals-query.html#intervals-wildcard\n// for details.\ntype IntervalQueryRuleWildcard struct {\n\tpattern  string\n\tanalyzer string\n\tuseField string\n}\n\n// NewIntervalQueryRuleWildcard initializes and returns a new instance\n// of IntervalQueryRuleWildcard.\nfunc NewIntervalQueryRuleWildcard(pattern string) *IntervalQueryRuleWildcard {\n\treturn &IntervalQueryRuleWildcard{pattern: pattern}\n}\n\n// Analyzer specifies the analyzer used to analyze terms in the query.\nfunc (r *IntervalQueryRuleWildcard) Analyzer(analyzer string) *IntervalQueryRuleWildcard {\n\tr.analyzer = analyzer\n\treturn r\n}\n\n// UseField, if specified, matches the intervals from this field rather than\n// the top-level field.\nfunc (r *IntervalQueryRuleWildcard) UseField(useField string) *IntervalQueryRuleWildcard {\n\tr.useField = useField\n\treturn r\n}\n\n// Source returns JSON for the function score query.\nfunc (r *IntervalQueryRuleWildcard) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tsource[\"pattern\"] = r.pattern\n\n\tif r.analyzer != \"\" {\n\t\tsource[\"analyzer\"] = r.analyzer\n\t}\n\tif r.useField != \"\" {\n\t\tsource[\"use_field\"] = r.useField\n\t}\n\n\treturn map[string]interface{}{\n\t\t\"wildcard\": source,\n\t}, nil\n}\n\n// isIntervalQueryRule implements the marker interface.\nfunc (r *IntervalQueryRuleWildcard) isIntervalQueryRule() bool {\n\treturn true\n}\n"
  },
  {
    "path": "search_queries_interval_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestIntervalQuery(t *testing.T) {\n\tq := NewIntervalQuery(\n\t\t\"my_text\",\n\t\tNewIntervalQueryRuleAllOf(\n\t\t\tNewIntervalQueryRuleMatch(\"my favorite food\").\n\t\t\t\tMaxGaps(0).\n\t\t\t\tOrdered(true).\n\t\t\t\tFilter(\n\t\t\t\t\tNewIntervalQueryFilter().\n\t\t\t\t\t\tNotContaining(\n\t\t\t\t\t\t\tNewIntervalQueryRuleMatch(\"salty\"),\n\t\t\t\t\t\t),\n\t\t\t\t),\n\t\t\tNewIntervalQueryRuleAnyOf(\n\t\t\t\tNewIntervalQueryRuleMatch(\"hot water\"),\n\t\t\t\tNewIntervalQueryRuleMatch(\"cold porridge\"),\n\t\t\t),\n\t\t).Ordered(true),\n\t)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"intervals\":{\"my_text\":{\"all_of\":{\"intervals\":[{\"match\":{\"filter\":{\"not_containing\":{\"match\":{\"query\":\"salty\"}}},\"max_gaps\":0,\"ordered\":true,\"query\":\"my favorite food\"}},{\"any_of\":{\"intervals\":[{\"match\":{\"query\":\"hot water\"}},{\"match\":{\"query\":\"cold porridge\"}}]}}],\"ordered\":true}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_match.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MatchQuery is a family of queries that accepts text/numerics/dates,\n// analyzes them, and constructs a query.\n//\n// To create a new MatchQuery, use NewMatchQuery. To create specific types\n// of queries, e.g. a match_phrase query, use NewMatchPhrQuery(...).Type(\"phrase\"),\n// or use one of the shortcuts e.g. NewMatchPhraseQuery(...).\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-match-query.html\ntype MatchQuery struct {\n\tname                string\n\ttext                interface{}\n\toperator            string // or / and\n\tanalyzer            string\n\tboost               *float64\n\tfuzziness           string\n\tprefixLength        *int\n\tmaxExpansions       *int\n\tminimumShouldMatch  string\n\tfuzzyRewrite        string\n\tlenient             *bool\n\tfuzzyTranspositions *bool\n\tzeroTermsQuery      string\n\tcutoffFrequency     *float64\n\tqueryName           string\n}\n\n// NewMatchQuery creates and initializes a new MatchQuery.\nfunc NewMatchQuery(name string, text interface{}) *MatchQuery {\n\treturn &MatchQuery{name: name, text: text}\n}\n\n// Operator sets the operator to use when using a boolean query.\n// Can be \"AND\" or \"OR\" (default).\nfunc (q *MatchQuery) Operator(operator string) *MatchQuery {\n\tq.operator = operator\n\treturn q\n}\n\n// Analyzer explicitly sets the analyzer to use. It defaults to use explicit\n// mapping config for the field, or, if not set, the default search analyzer.\nfunc (q *MatchQuery) Analyzer(analyzer string) *MatchQuery {\n\tq.analyzer = analyzer\n\treturn q\n}\n\n// Fuzziness sets the fuzziness when evaluated to a fuzzy query type.\n// Defaults to \"AUTO\".\nfunc (q *MatchQuery) Fuzziness(fuzziness string) *MatchQuery {\n\tq.fuzziness = fuzziness\n\treturn q\n}\n\n// PrefixLength sets the length of a length of common (non-fuzzy)\n// prefix for fuzzy match queries. It must be non-negative.\nfunc (q *MatchQuery) PrefixLength(prefixLength int) *MatchQuery {\n\tq.prefixLength = &prefixLength\n\treturn q\n}\n\n// MaxExpansions is used with fuzzy or prefix type queries. It specifies\n// the number of term expansions to use. It defaults to unbounded so that\n// its recommended to set it to a reasonable value for faster execution.\nfunc (q *MatchQuery) MaxExpansions(maxExpansions int) *MatchQuery {\n\tq.maxExpansions = &maxExpansions\n\treturn q\n}\n\n// CutoffFrequency can be a value in [0..1] (or an absolute number >=1).\n// It represents the maximum treshold of a terms document frequency to be\n// considered a low frequency term.\nfunc (q *MatchQuery) CutoffFrequency(cutoff float64) *MatchQuery {\n\tq.cutoffFrequency = &cutoff\n\treturn q\n}\n\n// MinimumShouldMatch sets the optional minimumShouldMatch value to\n// apply to the query.\nfunc (q *MatchQuery) MinimumShouldMatch(minimumShouldMatch string) *MatchQuery {\n\tq.minimumShouldMatch = minimumShouldMatch\n\treturn q\n}\n\n// FuzzyRewrite sets the fuzzy_rewrite parameter controlling how the\n// fuzzy query will get rewritten.\nfunc (q *MatchQuery) FuzzyRewrite(fuzzyRewrite string) *MatchQuery {\n\tq.fuzzyRewrite = fuzzyRewrite\n\treturn q\n}\n\n// FuzzyTranspositions sets whether transpositions are supported in\n// fuzzy queries.\n//\n// The default metric used by fuzzy queries to determine a match is\n// the Damerau-Levenshtein distance formula which supports transpositions.\n// Setting transposition to false will\n// * switch to classic Levenshtein distance.\n// * If not set, Damerau-Levenshtein distance metric will be used.\nfunc (q *MatchQuery) FuzzyTranspositions(fuzzyTranspositions bool) *MatchQuery {\n\tq.fuzzyTranspositions = &fuzzyTranspositions\n\treturn q\n}\n\n// Lenient specifies whether format based failures will be ignored.\nfunc (q *MatchQuery) Lenient(lenient bool) *MatchQuery {\n\tq.lenient = &lenient\n\treturn q\n}\n\n// ZeroTermsQuery can be \"all\" or \"none\".\nfunc (q *MatchQuery) ZeroTermsQuery(zeroTermsQuery string) *MatchQuery {\n\tq.zeroTermsQuery = zeroTermsQuery\n\treturn q\n}\n\n// Boost sets the boost to apply to this query.\nfunc (q *MatchQuery) Boost(boost float64) *MatchQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched filters per hit.\nfunc (q *MatchQuery) QueryName(queryName string) *MatchQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *MatchQuery) Source() (interface{}, error) {\n\t// {\"match\":{\"name\":{\"query\":\"value\",\"type\":\"boolean/phrase\"}}}\n\tsource := make(map[string]interface{})\n\n\tmatch := make(map[string]interface{})\n\tsource[\"match\"] = match\n\n\tquery := make(map[string]interface{})\n\tmatch[q.name] = query\n\n\tquery[\"query\"] = q.text\n\n\tif q.operator != \"\" {\n\t\tquery[\"operator\"] = q.operator\n\t}\n\tif q.analyzer != \"\" {\n\t\tquery[\"analyzer\"] = q.analyzer\n\t}\n\tif q.fuzziness != \"\" {\n\t\tquery[\"fuzziness\"] = q.fuzziness\n\t}\n\tif q.prefixLength != nil {\n\t\tquery[\"prefix_length\"] = *q.prefixLength\n\t}\n\tif q.maxExpansions != nil {\n\t\tquery[\"max_expansions\"] = *q.maxExpansions\n\t}\n\tif q.minimumShouldMatch != \"\" {\n\t\tquery[\"minimum_should_match\"] = q.minimumShouldMatch\n\t}\n\tif q.fuzzyRewrite != \"\" {\n\t\tquery[\"fuzzy_rewrite\"] = q.fuzzyRewrite\n\t}\n\tif q.lenient != nil {\n\t\tquery[\"lenient\"] = *q.lenient\n\t}\n\tif q.fuzzyTranspositions != nil {\n\t\tquery[\"fuzzy_transpositions\"] = *q.fuzzyTranspositions\n\t}\n\tif q.zeroTermsQuery != \"\" {\n\t\tquery[\"zero_terms_query\"] = q.zeroTermsQuery\n\t}\n\tif q.cutoffFrequency != nil {\n\t\tquery[\"cutoff_frequency\"] = *q.cutoffFrequency\n\t}\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_match_all.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"encoding/json\"\n\n// MatchAllQuery is the most simple query, which matches all documents,\n// giving them all a _score of 1.0.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-match-all-query.html\ntype MatchAllQuery struct {\n\tboost     *float64\n\tqueryName string\n}\n\n// NewMatchAllQuery creates and initializes a new match all query.\nfunc NewMatchAllQuery() *MatchAllQuery {\n\treturn &MatchAllQuery{}\n}\n\n// Boost sets the boost for this query. Documents matching this query will\n// (in addition to the normal weightings) have their score multiplied by the\n// boost provided.\nfunc (q *MatchAllQuery) Boost(boost float64) *MatchAllQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name.\nfunc (q *MatchAllQuery) QueryName(name string) *MatchAllQuery {\n\tq.queryName = name\n\treturn q\n}\n\n// Source returns JSON for the match all query.\nfunc (q *MatchAllQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"match_all\" : { ... }\n\t// }\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"match_all\"] = params\n\tif q.boost != nil {\n\t\tparams[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\treturn source, nil\n}\n\n// MarshalJSON enables serializing the type as JSON.\nfunc (q *MatchAllQuery) MarshalJSON() ([]byte, error) {\n\tif q == nil {\n\t\treturn nilByte, nil\n\t}\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn json.Marshal(src)\n}\n"
  },
  {
    "path": "search_queries_match_all_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMatchAllQuery(t *testing.T) {\n\tq := NewMatchAllQuery()\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_all\":{}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMatchAllQueryWithBoost(t *testing.T) {\n\tq := NewMatchAllQuery().Boost(3.14)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_all\":{\"boost\":3.14}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMatchAllQueryWithQueryName(t *testing.T) {\n\tq := NewMatchAllQuery().QueryName(\"qname\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_all\":{\"_name\":\"qname\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMatchAllMarshalJSON(t *testing.T) {\n\tin := NewMatchAllQuery().Boost(3.14)\n\tdata, err := json.Marshal(in)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_all\":{\"boost\":3.14}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_match_bool_prefix.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MatchBoolPrefixQuery query analyzes its input and constructs a bool query from the terms.\n// Each term except the last is used in a term query. The last term is used in a prefix query.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-match-bool-prefix-query.html\ntype MatchBoolPrefixQuery struct {\n\tname                string\n\tqueryText           interface{}\n\tanalyzer            string\n\tminimumShouldMatch  string\n\toperator            string\n\tfuzziness           string\n\tprefixLength        *int\n\tmaxExpansions       *int\n\tfuzzyTranspositions *bool\n\tfuzzyRewrite        string\n\tboost               *float64\n}\n\n// NewMatchBoolPrefixQuery creates and initializes a new MatchBoolPrefixQuery.\nfunc NewMatchBoolPrefixQuery(name string, queryText interface{}) *MatchBoolPrefixQuery {\n\treturn &MatchBoolPrefixQuery{name: name, queryText: queryText}\n}\n\n// Analyzer explicitly sets the analyzer to use. It defaults to use explicit\n// mapping config for the field, or, if not set, the default search analyzer.\nfunc (q *MatchBoolPrefixQuery) Analyzer(analyzer string) *MatchBoolPrefixQuery {\n\tq.analyzer = analyzer\n\treturn q\n}\n\n// MinimumShouldMatch sets the optional minimumShouldMatch value to apply to the query.\nfunc (q *MatchBoolPrefixQuery) MinimumShouldMatch(minimumShouldMatch string) *MatchBoolPrefixQuery {\n\tq.minimumShouldMatch = minimumShouldMatch\n\treturn q\n}\n\n// Operator sets the operator to use when using a boolean query.\n// Can be \"AND\" or \"OR\" (default).\nfunc (q *MatchBoolPrefixQuery) Operator(operator string) *MatchBoolPrefixQuery {\n\tq.operator = operator\n\treturn q\n}\n\n// Fuzziness sets the edit distance for fuzzy queries. Default is \"AUTO\".\nfunc (q *MatchBoolPrefixQuery) Fuzziness(fuzziness string) *MatchBoolPrefixQuery {\n\tq.fuzziness = fuzziness\n\treturn q\n}\n\n// PrefixLength is the number of beginning characters left unchanged for fuzzy matching. Defaults to 0.\nfunc (q *MatchBoolPrefixQuery) PrefixLength(prefixLength int) *MatchBoolPrefixQuery {\n\tq.prefixLength = &prefixLength\n\treturn q\n}\n\n// MaxExpansions sets the number of term expansions to use.\nfunc (q *MatchBoolPrefixQuery) MaxExpansions(n int) *MatchBoolPrefixQuery {\n\tq.maxExpansions = &n\n\treturn q\n}\n\n// FuzzyTranspositions if true, edits for fuzzy matching include transpositions of two adjacent\n// characters (ab → ba). Defaults to true.\nfunc (q *MatchBoolPrefixQuery) FuzzyTranspositions(fuzzyTranspositions bool) *MatchBoolPrefixQuery {\n\tq.fuzzyTranspositions = &fuzzyTranspositions\n\treturn q\n}\n\n// FuzzyRewrite sets the fuzzy_rewrite parameter controlling how the\n// fuzzy query will get rewritten.\nfunc (q *MatchBoolPrefixQuery) FuzzyRewrite(fuzzyRewrite string) *MatchBoolPrefixQuery {\n\tq.fuzzyRewrite = fuzzyRewrite\n\treturn q\n}\n\n// Boost sets the boost to apply to this query.\nfunc (q *MatchBoolPrefixQuery) Boost(boost float64) *MatchBoolPrefixQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *MatchBoolPrefixQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tmatch := make(map[string]interface{})\n\tsource[\"match_bool_prefix\"] = match\n\n\tquery := make(map[string]interface{})\n\tmatch[q.name] = query\n\n\tquery[\"query\"] = q.queryText\n\n\tif q.analyzer != \"\" {\n\t\tquery[\"analyzer\"] = q.analyzer\n\t}\n\tif q.minimumShouldMatch != \"\" {\n\t\tquery[\"minimum_should_match\"] = q.minimumShouldMatch\n\t}\n\tif q.operator != \"\" {\n\t\tquery[\"operator\"] = q.operator\n\t}\n\tif q.fuzziness != \"\" {\n\t\tquery[\"fuzziness\"] = q.fuzziness\n\t}\n\tif q.prefixLength != nil {\n\t\tquery[\"prefix_length\"] = *q.prefixLength\n\t}\n\tif q.maxExpansions != nil {\n\t\tquery[\"max_expansions\"] = *q.maxExpansions\n\t}\n\tif q.fuzzyTranspositions != nil {\n\t\tquery[\"fuzzy_transpositions\"] = *q.fuzzyTranspositions\n\t}\n\tif q.fuzzyRewrite != \"\" {\n\t\tquery[\"fuzzy_rewrite\"] = q.fuzzyRewrite\n\t}\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_match_bool_prefix_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMatchBoolPrefixQuery(t *testing.T) {\n\tq := NewMatchBoolPrefixQuery(\"query_name\", \"this is a test\").\n\t\tAnalyzer(\"custom_analyzer\").\n\t\tMinimumShouldMatch(\"75%\").\n\t\tOperator(\"AND\").\n\t\tFuzziness(\"AUTO\").\n\t\tPrefixLength(1).\n\t\tMaxExpansions(5).\n\t\tFuzzyTranspositions(false).\n\t\tFuzzyRewrite(\"constant_score\").\n\t\tBoost(0.3)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_bool_prefix\":{\"query_name\":{\"analyzer\":\"custom_analyzer\",\"boost\":0.3,\"fuzziness\":\"AUTO\",\"fuzzy_rewrite\":\"constant_score\",\"fuzzy_transpositions\":false,\"max_expansions\":5,\"minimum_should_match\":\"75%\",\"operator\":\"AND\",\"prefix_length\":1,\"query\":\"this is a test\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_match_none.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MatchNoneQuery returns no documents. It is the inverse of\n// MatchAllQuery.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-match-all-query.html\ntype MatchNoneQuery struct {\n\tqueryName string\n}\n\n// NewMatchNoneQuery creates and initializes a new match none query.\nfunc NewMatchNoneQuery() *MatchNoneQuery {\n\treturn &MatchNoneQuery{}\n}\n\n// QueryName sets the query name.\nfunc (q *MatchNoneQuery) QueryName(name string) *MatchNoneQuery {\n\tq.queryName = name\n\treturn q\n}\n\n// Source returns JSON for the match none query.\nfunc (q MatchNoneQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"match_none\" : { ... }\n\t// }\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"match_none\"] = params\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_match_none_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMatchNoneQuery(t *testing.T) {\n\tq := NewMatchNoneQuery()\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_none\":{}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMatchNoneQueryWithQueryName(t *testing.T) {\n\tq := NewMatchNoneQuery().QueryName(\"qname\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_none\":{\"_name\":\"qname\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_match_phrase.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MatchPhraseQuery analyzes the text and creates a phrase query out of\n// the analyzed text.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-match-query-phrase.html\ntype MatchPhraseQuery struct {\n\tname           string\n\tvalue          interface{}\n\tanalyzer       string\n\tslop           *int\n\tboost          *float64\n\tqueryName      string\n\tzeroTermsQuery string\n}\n\n// NewMatchPhraseQuery creates and initializes a new MatchPhraseQuery.\nfunc NewMatchPhraseQuery(name string, value interface{}) *MatchPhraseQuery {\n\treturn &MatchPhraseQuery{name: name, value: value}\n}\n\n// Analyzer explicitly sets the analyzer to use. It defaults to use explicit\n// mapping config for the field, or, if not set, the default search analyzer.\nfunc (q *MatchPhraseQuery) Analyzer(analyzer string) *MatchPhraseQuery {\n\tq.analyzer = analyzer\n\treturn q\n}\n\n// Slop sets the phrase slop if evaluated to a phrase query type.\nfunc (q *MatchPhraseQuery) Slop(slop int) *MatchPhraseQuery {\n\tq.slop = &slop\n\treturn q\n}\n\n// ZeroTermsQuery can be \"all\" or \"none\".\nfunc (q *MatchPhraseQuery) ZeroTermsQuery(zeroTermsQuery string) *MatchPhraseQuery {\n\tq.zeroTermsQuery = zeroTermsQuery\n\treturn q\n}\n\n// Boost sets the boost to apply to this query.\nfunc (q *MatchPhraseQuery) Boost(boost float64) *MatchPhraseQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched filters per hit.\nfunc (q *MatchPhraseQuery) QueryName(queryName string) *MatchPhraseQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *MatchPhraseQuery) Source() (interface{}, error) {\n\t// {\"match_phrase\":{\"name\":{\"query\":\"value\",\"analyzer\":\"my_analyzer\"}}}\n\tsource := make(map[string]interface{})\n\n\tmatch := make(map[string]interface{})\n\tsource[\"match_phrase\"] = match\n\n\tquery := make(map[string]interface{})\n\tmatch[q.name] = query\n\n\tquery[\"query\"] = q.value\n\n\tif q.analyzer != \"\" {\n\t\tquery[\"analyzer\"] = q.analyzer\n\t}\n\tif q.slop != nil {\n\t\tquery[\"slop\"] = *q.slop\n\t}\n\tif q.zeroTermsQuery != \"\" {\n\t\tquery[\"zero_terms_query\"] = q.zeroTermsQuery\n\t}\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_match_phrase_prefix.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// MatchPhrasePrefixQuery is the same as match_phrase, except that it allows for\n// prefix matches on the last term in the text.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-match-query-phrase-prefix.html\ntype MatchPhrasePrefixQuery struct {\n\tname          string\n\tvalue         interface{}\n\tanalyzer      string\n\tslop          *int\n\tmaxExpansions *int\n\tboost         *float64\n\tqueryName     string\n}\n\n// NewMatchPhrasePrefixQuery creates and initializes a new MatchPhrasePrefixQuery.\nfunc NewMatchPhrasePrefixQuery(name string, value interface{}) *MatchPhrasePrefixQuery {\n\treturn &MatchPhrasePrefixQuery{name: name, value: value}\n}\n\n// Analyzer explicitly sets the analyzer to use. It defaults to use explicit\n// mapping config for the field, or, if not set, the default search analyzer.\nfunc (q *MatchPhrasePrefixQuery) Analyzer(analyzer string) *MatchPhrasePrefixQuery {\n\tq.analyzer = analyzer\n\treturn q\n}\n\n// Slop sets the phrase slop if evaluated to a phrase query type.\nfunc (q *MatchPhrasePrefixQuery) Slop(slop int) *MatchPhrasePrefixQuery {\n\tq.slop = &slop\n\treturn q\n}\n\n// MaxExpansions sets the number of term expansions to use.\nfunc (q *MatchPhrasePrefixQuery) MaxExpansions(n int) *MatchPhrasePrefixQuery {\n\tq.maxExpansions = &n\n\treturn q\n}\n\n// Boost sets the boost to apply to this query.\nfunc (q *MatchPhrasePrefixQuery) Boost(boost float64) *MatchPhrasePrefixQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched filters per hit.\nfunc (q *MatchPhrasePrefixQuery) QueryName(queryName string) *MatchPhrasePrefixQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *MatchPhrasePrefixQuery) Source() (interface{}, error) {\n\t// {\"match_phrase_prefix\":{\"name\":{\"query\":\"value\",\"max_expansions\":10}}}\n\tsource := make(map[string]interface{})\n\n\tmatch := make(map[string]interface{})\n\tsource[\"match_phrase_prefix\"] = match\n\n\tquery := make(map[string]interface{})\n\tmatch[q.name] = query\n\n\tquery[\"query\"] = q.value\n\n\tif q.analyzer != \"\" {\n\t\tquery[\"analyzer\"] = q.analyzer\n\t}\n\tif q.slop != nil {\n\t\tquery[\"slop\"] = *q.slop\n\t}\n\tif q.maxExpansions != nil {\n\t\tquery[\"max_expansions\"] = *q.maxExpansions\n\t}\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_match_phrase_prefix_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMatchPhrasePrefixQuery(t *testing.T) {\n\tq := NewMatchPhrasePrefixQuery(\"message\", \"this is a test\").Boost(0.3).MaxExpansions(5)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_phrase_prefix\":{\"message\":{\"boost\":0.3,\"max_expansions\":5,\"query\":\"this is a test\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_match_phrase_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMatchPhraseQuery(t *testing.T) {\n\tq := NewMatchPhraseQuery(\"message\", \"this is a test\").\n\t\tAnalyzer(\"my_analyzer\").\n\t\tBoost(0.7)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_phrase\":{\"message\":{\"analyzer\":\"my_analyzer\",\"boost\":0.7,\"query\":\"this is a test\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_match_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMatchQuery(t *testing.T) {\n\tq := NewMatchQuery(\"message\", \"this is a test\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match\":{\"message\":{\"query\":\"this is a test\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMatchQueryWithOptions(t *testing.T) {\n\tq := NewMatchQuery(\"message\", \"this is a test\").Analyzer(\"whitespace\").Operator(\"or\").Boost(2.5)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match\":{\"message\":{\"analyzer\":\"whitespace\",\"boost\":2.5,\"operator\":\"or\",\"query\":\"this is a test\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMatchQueryWithInt64(t *testing.T) {\n\tq := NewMatchQuery(\"message\", 459751182159713792)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match\":{\"message\":{\"query\":459751182159713792}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_more_like_this.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"errors\"\n\n// MoreLikeThis query (MLT Query) finds documents that are \"like\" a given\n// set of documents. In order to do so, MLT selects a set of representative\n// terms of these input documents, forms a query using these terms, executes\n// the query and returns the results. The user controls the input documents,\n// how the terms should be selected and how the query is formed.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-mlt-query.html\ntype MoreLikeThisQuery struct {\n\tfields                 []string\n\tdocs                   []*MoreLikeThisQueryItem\n\tunlikeDocs             []*MoreLikeThisQueryItem\n\tinclude                *bool\n\tminimumShouldMatch     string\n\tminTermFreq            *int\n\tmaxQueryTerms          *int\n\tstopWords              []string\n\tminDocFreq             *int\n\tmaxDocFreq             *int\n\tminWordLength          *int\n\tmaxWordLength          *int\n\tboostTerms             *float64\n\tboost                  *float64\n\tanalyzer               string\n\tfailOnUnsupportedField *bool\n\tqueryName              string\n}\n\n// NewMoreLikeThisQuery creates and initializes a new MoreLikeThisQuery.\nfunc NewMoreLikeThisQuery() *MoreLikeThisQuery {\n\treturn &MoreLikeThisQuery{\n\t\tfields:     make([]string, 0),\n\t\tstopWords:  make([]string, 0),\n\t\tdocs:       make([]*MoreLikeThisQueryItem, 0),\n\t\tunlikeDocs: make([]*MoreLikeThisQueryItem, 0),\n\t}\n}\n\n// Field adds one or more field names to the query.\nfunc (q *MoreLikeThisQuery) Field(fields ...string) *MoreLikeThisQuery {\n\tq.fields = append(q.fields, fields...)\n\treturn q\n}\n\n// StopWord sets the stopwords. Any word in this set is considered\n// \"uninteresting\" and ignored. Even if your Analyzer allows stopwords,\n// you might want to tell the MoreLikeThis code to ignore them, as for\n// the purposes of document similarity it seems reasonable to assume that\n// \"a stop word is never interesting\".\nfunc (q *MoreLikeThisQuery) StopWord(stopWords ...string) *MoreLikeThisQuery {\n\tq.stopWords = append(q.stopWords, stopWords...)\n\treturn q\n}\n\n// LikeText sets the text to use in order to find documents that are \"like\" this.\nfunc (q *MoreLikeThisQuery) LikeText(likeTexts ...string) *MoreLikeThisQuery {\n\tfor _, s := range likeTexts {\n\t\titem := NewMoreLikeThisQueryItem().LikeText(s)\n\t\tq.docs = append(q.docs, item)\n\t}\n\treturn q\n}\n\n// LikeItems sets the documents to use in order to find documents that are \"like\" this.\nfunc (q *MoreLikeThisQuery) LikeItems(docs ...*MoreLikeThisQueryItem) *MoreLikeThisQuery {\n\tq.docs = append(q.docs, docs...)\n\treturn q\n}\n\n// IgnoreLikeText sets the text from which the terms should not be selected from.\nfunc (q *MoreLikeThisQuery) IgnoreLikeText(ignoreLikeText ...string) *MoreLikeThisQuery {\n\tfor _, s := range ignoreLikeText {\n\t\titem := NewMoreLikeThisQueryItem().LikeText(s)\n\t\tq.unlikeDocs = append(q.unlikeDocs, item)\n\t}\n\treturn q\n}\n\n// IgnoreLikeItems sets the documents from which the terms should not be selected from.\nfunc (q *MoreLikeThisQuery) IgnoreLikeItems(ignoreDocs ...*MoreLikeThisQueryItem) *MoreLikeThisQuery {\n\tq.unlikeDocs = append(q.unlikeDocs, ignoreDocs...)\n\treturn q\n}\n\n// Ids sets the document ids to use in order to find documents that are \"like\" this.\nfunc (q *MoreLikeThisQuery) Ids(ids ...string) *MoreLikeThisQuery {\n\tfor _, id := range ids {\n\t\titem := NewMoreLikeThisQueryItem().Id(id)\n\t\tq.docs = append(q.docs, item)\n\t}\n\treturn q\n}\n\n// Include specifies whether the input documents should also be included\n// in the results returned. Defaults to false.\nfunc (q *MoreLikeThisQuery) Include(include bool) *MoreLikeThisQuery {\n\tq.include = &include\n\treturn q\n}\n\n// MinimumShouldMatch sets the number of terms that must match the generated\n// query expressed in the common syntax for minimum should match.\n// The default value is \"30%\".\n//\n// This used to be \"PercentTermsToMatch\" in Elasticsearch versions before 2.0.\nfunc (q *MoreLikeThisQuery) MinimumShouldMatch(minimumShouldMatch string) *MoreLikeThisQuery {\n\tq.minimumShouldMatch = minimumShouldMatch\n\treturn q\n}\n\n// MinTermFreq is the frequency below which terms will be ignored in the\n// source doc. The default frequency is 2.\nfunc (q *MoreLikeThisQuery) MinTermFreq(minTermFreq int) *MoreLikeThisQuery {\n\tq.minTermFreq = &minTermFreq\n\treturn q\n}\n\n// MaxQueryTerms sets the maximum number of query terms that will be included\n// in any generated query. It defaults to 25.\nfunc (q *MoreLikeThisQuery) MaxQueryTerms(maxQueryTerms int) *MoreLikeThisQuery {\n\tq.maxQueryTerms = &maxQueryTerms\n\treturn q\n}\n\n// MinDocFreq sets the frequency at which words will be ignored which do\n// not occur in at least this many docs. The default is 5.\nfunc (q *MoreLikeThisQuery) MinDocFreq(minDocFreq int) *MoreLikeThisQuery {\n\tq.minDocFreq = &minDocFreq\n\treturn q\n}\n\n// MaxDocFreq sets the maximum frequency for which words may still appear.\n// Words that appear in more than this many docs will be ignored.\n// It defaults to unbounded.\nfunc (q *MoreLikeThisQuery) MaxDocFreq(maxDocFreq int) *MoreLikeThisQuery {\n\tq.maxDocFreq = &maxDocFreq\n\treturn q\n}\n\n// MinWordLength sets the minimum word length below which words will be\n// ignored. It defaults to 0.\nfunc (q *MoreLikeThisQuery) MinWordLength(minWordLength int) *MoreLikeThisQuery {\n\tq.minWordLength = &minWordLength\n\treturn q\n}\n\n// MaxWordLength sets the maximum word length above which words will be ignored.\n// Defaults to unbounded (0).\nfunc (q *MoreLikeThisQuery) MaxWordLength(maxWordLength int) *MoreLikeThisQuery {\n\tq.maxWordLength = &maxWordLength\n\treturn q\n}\n\n// BoostTerms sets the boost factor to use when boosting terms.\n// It defaults to 1.\nfunc (q *MoreLikeThisQuery) BoostTerms(boostTerms float64) *MoreLikeThisQuery {\n\tq.boostTerms = &boostTerms\n\treturn q\n}\n\n// Analyzer specifies the analyzer that will be use to analyze the text.\n// Defaults to the analyzer associated with the field.\nfunc (q *MoreLikeThisQuery) Analyzer(analyzer string) *MoreLikeThisQuery {\n\tq.analyzer = analyzer\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *MoreLikeThisQuery) Boost(boost float64) *MoreLikeThisQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// FailOnUnsupportedField indicates whether to fail or return no result\n// when this query is run against a field which is not supported such as\n// a binary/numeric field.\nfunc (q *MoreLikeThisQuery) FailOnUnsupportedField(fail bool) *MoreLikeThisQuery {\n\tq.failOnUnsupportedField = &fail\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched_filters per hit.\nfunc (q *MoreLikeThisQuery) QueryName(queryName string) *MoreLikeThisQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source creates the source for the MLT query.\n// It may return an error if the caller forgot to specify any documents to\n// be \"liked\" in the MoreLikeThisQuery.\nfunc (q *MoreLikeThisQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"match_all\" : { ... }\n\t// }\n\tif len(q.docs) == 0 {\n\t\treturn nil, errors.New(`more_like_this requires some documents to be \"liked\"`)\n\t}\n\n\tsource := make(map[string]interface{})\n\n\tparams := make(map[string]interface{})\n\tsource[\"more_like_this\"] = params\n\n\tif len(q.fields) > 0 {\n\t\tparams[\"fields\"] = q.fields\n\t}\n\n\tvar likes []interface{}\n\tfor _, doc := range q.docs {\n\t\tsrc, err := doc.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tlikes = append(likes, src)\n\t}\n\tparams[\"like\"] = likes\n\n\tif len(q.unlikeDocs) > 0 {\n\t\tvar dontLikes []interface{}\n\t\tfor _, doc := range q.unlikeDocs {\n\t\t\tsrc, err := doc.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdontLikes = append(dontLikes, src)\n\t\t}\n\t\tparams[\"unlike\"] = dontLikes\n\t}\n\n\tif q.minimumShouldMatch != \"\" {\n\t\tparams[\"minimum_should_match\"] = q.minimumShouldMatch\n\t}\n\tif q.minTermFreq != nil {\n\t\tparams[\"min_term_freq\"] = *q.minTermFreq\n\t}\n\tif q.maxQueryTerms != nil {\n\t\tparams[\"max_query_terms\"] = *q.maxQueryTerms\n\t}\n\tif len(q.stopWords) > 0 {\n\t\tparams[\"stop_words\"] = q.stopWords\n\t}\n\tif q.minDocFreq != nil {\n\t\tparams[\"min_doc_freq\"] = *q.minDocFreq\n\t}\n\tif q.maxDocFreq != nil {\n\t\tparams[\"max_doc_freq\"] = *q.maxDocFreq\n\t}\n\tif q.minWordLength != nil {\n\t\tparams[\"min_word_length\"] = *q.minWordLength\n\t}\n\tif q.maxWordLength != nil {\n\t\tparams[\"max_word_length\"] = *q.maxWordLength\n\t}\n\tif q.boostTerms != nil {\n\t\tparams[\"boost_terms\"] = *q.boostTerms\n\t}\n\tif q.boost != nil {\n\t\tparams[\"boost\"] = *q.boost\n\t}\n\tif q.analyzer != \"\" {\n\t\tparams[\"analyzer\"] = q.analyzer\n\t}\n\tif q.failOnUnsupportedField != nil {\n\t\tparams[\"fail_on_unsupported_field\"] = *q.failOnUnsupportedField\n\t}\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\tif q.include != nil {\n\t\tparams[\"include\"] = *q.include\n\t}\n\n\treturn source, nil\n}\n\n// -- MoreLikeThisQueryItem --\n\n// MoreLikeThisQueryItem represents a single item of a MoreLikeThisQuery\n// to be \"liked\" or \"unliked\".\ntype MoreLikeThisQueryItem struct {\n\tlikeText string\n\n\tindex       string\n\ttyp         string\n\tid          string\n\tdoc         interface{}\n\tfields      []string\n\trouting     string\n\tfsc         *FetchSourceContext\n\tversion     int64\n\tversionType string\n}\n\n// NewMoreLikeThisQueryItem creates and initializes a MoreLikeThisQueryItem.\nfunc NewMoreLikeThisQueryItem() *MoreLikeThisQueryItem {\n\treturn &MoreLikeThisQueryItem{\n\t\tversion: -1,\n\t}\n}\n\n// LikeText represents a text to be \"liked\".\nfunc (item *MoreLikeThisQueryItem) LikeText(likeText string) *MoreLikeThisQueryItem {\n\titem.likeText = likeText\n\treturn item\n}\n\n// Index represents the index of the item.\nfunc (item *MoreLikeThisQueryItem) Index(index string) *MoreLikeThisQueryItem {\n\titem.index = index\n\treturn item\n}\n\n// Type represents the document type of the item.\n//\n// Deprecated: Types are in the process of being removed.\nfunc (item *MoreLikeThisQueryItem) Type(typ string) *MoreLikeThisQueryItem {\n\titem.typ = typ\n\treturn item\n}\n\n// Id represents the document id of the item.\nfunc (item *MoreLikeThisQueryItem) Id(id string) *MoreLikeThisQueryItem {\n\titem.id = id\n\treturn item\n}\n\n// Doc represents a raw document template for the item.\nfunc (item *MoreLikeThisQueryItem) Doc(doc interface{}) *MoreLikeThisQueryItem {\n\titem.doc = doc\n\treturn item\n}\n\n// Fields represents the list of fields of the item.\nfunc (item *MoreLikeThisQueryItem) Fields(fields ...string) *MoreLikeThisQueryItem {\n\titem.fields = append(item.fields, fields...)\n\treturn item\n}\n\n// Routing sets the routing associated with the item.\nfunc (item *MoreLikeThisQueryItem) Routing(routing string) *MoreLikeThisQueryItem {\n\titem.routing = routing\n\treturn item\n}\n\n// FetchSourceContext represents the fetch source of the item which controls\n// if and how _source should be returned.\nfunc (item *MoreLikeThisQueryItem) FetchSourceContext(fsc *FetchSourceContext) *MoreLikeThisQueryItem {\n\titem.fsc = fsc\n\treturn item\n}\n\n// Version specifies the version of the item.\nfunc (item *MoreLikeThisQueryItem) Version(version int64) *MoreLikeThisQueryItem {\n\titem.version = version\n\treturn item\n}\n\n// VersionType represents the version type of the item.\nfunc (item *MoreLikeThisQueryItem) VersionType(versionType string) *MoreLikeThisQueryItem {\n\titem.versionType = versionType\n\treturn item\n}\n\n// Source returns the JSON-serializable fragment of the entity.\nfunc (item *MoreLikeThisQueryItem) Source() (interface{}, error) {\n\tif item.likeText != \"\" {\n\t\treturn item.likeText, nil\n\t}\n\n\tsource := make(map[string]interface{})\n\n\tif item.index != \"\" {\n\t\tsource[\"_index\"] = item.index\n\t}\n\tif item.typ != \"\" {\n\t\tsource[\"_type\"] = item.typ\n\t}\n\tif item.id != \"\" {\n\t\tsource[\"_id\"] = item.id\n\t}\n\tif item.doc != nil {\n\t\tsource[\"doc\"] = item.doc\n\t}\n\tif len(item.fields) > 0 {\n\t\tsource[\"fields\"] = item.fields\n\t}\n\tif item.routing != \"\" {\n\t\tsource[\"routing\"] = item.routing\n\t}\n\tif item.fsc != nil {\n\t\tsrc, err := item.fsc.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"_source\"] = src\n\t}\n\tif item.version >= 0 {\n\t\tsource[\"_version\"] = item.version\n\t}\n\tif item.versionType != \"\" {\n\t\tsource[\"_version_type\"] = item.versionType\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_more_like_this_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMoreLikeThisQuerySourceWithLikeText(t *testing.T) {\n\tq := NewMoreLikeThisQuery().LikeText(\"Golang topic\").Field(\"message\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(data)\n\texpected := `{\"more_like_this\":{\"fields\":[\"message\"],\"like\":[\"Golang topic\"]}}`\n\tif got != expected {\n\t\tt.Fatalf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMoreLikeThisQuerySourceWithLikeAndUnlikeItems(t *testing.T) {\n\tq := NewMoreLikeThisQuery()\n\tq = q.LikeItems(\n\t\tNewMoreLikeThisQueryItem().Id(\"1\"),\n\t\tNewMoreLikeThisQueryItem().Index(testIndexName2).Type(\"comment\").Id(\"2\").Routing(\"routing_id\"),\n\t)\n\tq = q.IgnoreLikeItems(NewMoreLikeThisQueryItem().Id(\"3\"))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(data)\n\texpected := `{\"more_like_this\":{\"like\":[{\"_id\":\"1\"},{\"_id\":\"2\",\"_index\":\"elastic-test2\",\"_type\":\"comment\",\"routing\":\"routing_id\"}],\"unlike\":[{\"_id\":\"3\"}]}}`\n\tif got != expected {\n\t\tt.Fatalf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMoreLikeThisQuery(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another Golang topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Common query\n\tmltq := NewMoreLikeThisQuery().LikeText(\"Golang topic\").Field(\"message\")\n\tres, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(mltq).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n}\n"
  },
  {
    "path": "search_queries_multi_match.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\n// MultiMatchQuery builds on the MatchQuery to allow multi-field queries.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html\ntype MultiMatchQuery struct {\n\ttext               interface{}\n\tfields             []string\n\tfieldBoosts        map[string]*float64\n\ttyp                string // best_fields, boolean, most_fields, cross_fields, phrase, phrase_prefix\n\toperator           string // AND or OR\n\tanalyzer           string\n\tboost              *float64\n\tslop               *int\n\tfuzziness          string\n\tprefixLength       *int\n\tmaxExpansions      *int\n\tminimumShouldMatch string\n\trewrite            string\n\tfuzzyRewrite       string\n\ttieBreaker         *float64\n\tlenient            *bool\n\tcutoffFrequency    *float64\n\tzeroTermsQuery     string\n\tqueryName          string\n}\n\n// MultiMatchQuery creates and initializes a new MultiMatchQuery.\nfunc NewMultiMatchQuery(text interface{}, fields ...string) *MultiMatchQuery {\n\tq := &MultiMatchQuery{\n\t\ttext:        text,\n\t\tfieldBoosts: make(map[string]*float64),\n\t}\n\tq.fields = append(q.fields, fields...)\n\treturn q\n}\n\n// Field adds a field to run the multi match against.\nfunc (q *MultiMatchQuery) Field(field string) *MultiMatchQuery {\n\tq.fields = append(q.fields, field)\n\treturn q\n}\n\n// FieldWithBoost adds a field to run the multi match against with a specific boost.\nfunc (q *MultiMatchQuery) FieldWithBoost(field string, boost float64) *MultiMatchQuery {\n\tq.fields = append(q.fields, field)\n\tq.fieldBoosts[field] = &boost\n\treturn q\n}\n\n// Type can be \"best_fields\", \"boolean\", \"most_fields\", \"cross_fields\",\n// \"phrase\", \"phrase_prefix\" or \"bool_prefix\"\nfunc (q *MultiMatchQuery) Type(typ string) *MultiMatchQuery {\n\tswitch strings.ToLower(typ) {\n\tdefault: // best_fields / boolean\n\t\tq.typ = \"best_fields\"\n\tcase \"most_fields\":\n\t\tq.typ = \"most_fields\"\n\tcase \"cross_fields\":\n\t\tq.typ = \"cross_fields\"\n\tcase \"phrase\":\n\t\tq.typ = \"phrase\"\n\tcase \"phrase_prefix\":\n\t\tq.typ = \"phrase_prefix\"\n\tcase \"bool_prefix\":\n\t\tq.typ = \"bool_prefix\"\n\t}\n\treturn q\n}\n\n// Operator sets the operator to use when using boolean query.\n// It can be either AND or OR (default).\nfunc (q *MultiMatchQuery) Operator(operator string) *MultiMatchQuery {\n\tq.operator = operator\n\treturn q\n}\n\n// Analyzer sets the analyzer to use explicitly. It defaults to use explicit\n// mapping config for the field, or, if not set, the default search analyzer.\nfunc (q *MultiMatchQuery) Analyzer(analyzer string) *MultiMatchQuery {\n\tq.analyzer = analyzer\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *MultiMatchQuery) Boost(boost float64) *MultiMatchQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// Slop sets the phrase slop if evaluated to a phrase query type.\nfunc (q *MultiMatchQuery) Slop(slop int) *MultiMatchQuery {\n\tq.slop = &slop\n\treturn q\n}\n\n// Fuzziness sets the fuzziness used when evaluated to a fuzzy query type.\n// It defaults to \"AUTO\".\nfunc (q *MultiMatchQuery) Fuzziness(fuzziness string) *MultiMatchQuery {\n\tq.fuzziness = fuzziness\n\treturn q\n}\n\n// PrefixLength for the fuzzy process.\nfunc (q *MultiMatchQuery) PrefixLength(prefixLength int) *MultiMatchQuery {\n\tq.prefixLength = &prefixLength\n\treturn q\n}\n\n// MaxExpansions is the number of term expansions to use when using fuzzy\n// or prefix type query. It defaults to unbounded so it's recommended\n// to set it to a reasonable value for faster execution.\nfunc (q *MultiMatchQuery) MaxExpansions(maxExpansions int) *MultiMatchQuery {\n\tq.maxExpansions = &maxExpansions\n\treturn q\n}\n\n// MinimumShouldMatch represents the minimum number of optional should clauses\n// to match.\nfunc (q *MultiMatchQuery) MinimumShouldMatch(minimumShouldMatch string) *MultiMatchQuery {\n\tq.minimumShouldMatch = minimumShouldMatch\n\treturn q\n}\n\nfunc (q *MultiMatchQuery) Rewrite(rewrite string) *MultiMatchQuery {\n\tq.rewrite = rewrite\n\treturn q\n}\n\nfunc (q *MultiMatchQuery) FuzzyRewrite(fuzzyRewrite string) *MultiMatchQuery {\n\tq.fuzzyRewrite = fuzzyRewrite\n\treturn q\n}\n\n// TieBreaker for \"best-match\" disjunction queries (OR queries).\n// The tie breaker capability allows documents that match more than one\n// query clause (in this case on more than one field) to be scored better\n// than documents that match only the best of the fields, without confusing\n// this with the better case of two distinct matches in the multiple fields.\n//\n// A tie-breaker value of 1.0 is interpreted as a signal to score queries as\n// \"most-match\" queries where all matching query clauses are considered for scoring.\nfunc (q *MultiMatchQuery) TieBreaker(tieBreaker float64) *MultiMatchQuery {\n\tq.tieBreaker = &tieBreaker\n\treturn q\n}\n\n// Lenient indicates whether format based failures will be ignored.\nfunc (q *MultiMatchQuery) Lenient(lenient bool) *MultiMatchQuery {\n\tq.lenient = &lenient\n\treturn q\n}\n\n// CutoffFrequency sets a cutoff value in [0..1] (or absolute number >=1)\n// representing the maximum threshold of a terms document frequency to be\n// considered a low frequency term.\nfunc (q *MultiMatchQuery) CutoffFrequency(cutoff float64) *MultiMatchQuery {\n\tq.cutoffFrequency = &cutoff\n\treturn q\n}\n\n// ZeroTermsQuery can be \"all\" or \"none\".\nfunc (q *MultiMatchQuery) ZeroTermsQuery(zeroTermsQuery string) *MultiMatchQuery {\n\tq.zeroTermsQuery = zeroTermsQuery\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched filters per hit.\nfunc (q *MultiMatchQuery) QueryName(queryName string) *MultiMatchQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the query.\nfunc (q *MultiMatchQuery) Source() (interface{}, error) {\n\t//\n\t// {\n\t//   \"multi_match\" : {\n\t//     \"query\" : \"this is a test\",\n\t//     \"fields\" : [ \"subject\", \"message\" ]\n\t//   }\n\t// }\n\n\tsource := make(map[string]interface{})\n\n\tmultiMatch := make(map[string]interface{})\n\tsource[\"multi_match\"] = multiMatch\n\n\tmultiMatch[\"query\"] = q.text\n\n\tvar fields []string\n\tfor _, field := range q.fields {\n\t\tif boost, found := q.fieldBoosts[field]; found {\n\t\t\tif boost != nil {\n\t\t\t\tfields = append(fields, fmt.Sprintf(\"%s^%f\", field, *boost))\n\t\t\t} else {\n\t\t\t\tfields = append(fields, field)\n\t\t\t}\n\t\t} else {\n\t\t\tfields = append(fields, field)\n\t\t}\n\t}\n\tif fields == nil {\n\t\tmultiMatch[\"fields\"] = []string{}\n\t} else {\n\t\tmultiMatch[\"fields\"] = fields\n\t}\n\n\tif q.typ != \"\" {\n\t\tmultiMatch[\"type\"] = q.typ\n\t}\n\n\tif q.operator != \"\" {\n\t\tmultiMatch[\"operator\"] = q.operator\n\t}\n\tif q.analyzer != \"\" {\n\t\tmultiMatch[\"analyzer\"] = q.analyzer\n\t}\n\tif q.boost != nil {\n\t\tmultiMatch[\"boost\"] = *q.boost\n\t}\n\tif q.slop != nil {\n\t\tmultiMatch[\"slop\"] = *q.slop\n\t}\n\tif q.fuzziness != \"\" {\n\t\tmultiMatch[\"fuzziness\"] = q.fuzziness\n\t}\n\tif q.prefixLength != nil {\n\t\tmultiMatch[\"prefix_length\"] = *q.prefixLength\n\t}\n\tif q.maxExpansions != nil {\n\t\tmultiMatch[\"max_expansions\"] = *q.maxExpansions\n\t}\n\tif q.minimumShouldMatch != \"\" {\n\t\tmultiMatch[\"minimum_should_match\"] = q.minimumShouldMatch\n\t}\n\tif q.rewrite != \"\" {\n\t\tmultiMatch[\"rewrite\"] = q.rewrite\n\t}\n\tif q.fuzzyRewrite != \"\" {\n\t\tmultiMatch[\"fuzzy_rewrite\"] = q.fuzzyRewrite\n\t}\n\tif q.tieBreaker != nil {\n\t\tmultiMatch[\"tie_breaker\"] = *q.tieBreaker\n\t}\n\tif q.lenient != nil {\n\t\tmultiMatch[\"lenient\"] = *q.lenient\n\t}\n\tif q.cutoffFrequency != nil {\n\t\tmultiMatch[\"cutoff_frequency\"] = *q.cutoffFrequency\n\t}\n\tif q.zeroTermsQuery != \"\" {\n\t\tmultiMatch[\"zero_terms_query\"] = q.zeroTermsQuery\n\t}\n\tif q.queryName != \"\" {\n\t\tmultiMatch[\"_name\"] = q.queryName\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_multi_match_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestMultiMatchQuery(t *testing.T) {\n\tq := NewMultiMatchQuery(\"this is a test\", \"subject\", \"message\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[\"subject\",\"message\"],\"query\":\"this is a test\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiMatchQueryWithNoFields(t *testing.T) {\n\tq := NewMultiMatchQuery(\"accident\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[],\"query\":\"accident\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiMatchQueryBestFields(t *testing.T) {\n\tq := NewMultiMatchQuery(\"this is a test\", \"subject\", \"message\").Type(\"best_fields\").TieBreaker(0)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[\"subject\",\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0,\"type\":\"best_fields\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiMatchQueryMostFields(t *testing.T) {\n\tq := NewMultiMatchQuery(\"this is a test\", \"subject\", \"message\").Type(\"most_fields\").TieBreaker(1)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[\"subject\",\"message\"],\"query\":\"this is a test\",\"tie_breaker\":1,\"type\":\"most_fields\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiMatchQueryCrossFields(t *testing.T) {\n\tq := NewMultiMatchQuery(\"this is a test\", \"subject\", \"message\").Type(\"cross_fields\").TieBreaker(0)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[\"subject\",\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0,\"type\":\"cross_fields\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiMatchQueryPhrase(t *testing.T) {\n\tq := NewMultiMatchQuery(\"this is a test\", \"subject\", \"message\").Type(\"phrase\").TieBreaker(0)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[\"subject\",\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0,\"type\":\"phrase\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiMatchQueryPhrasePrefix(t *testing.T) {\n\tq := NewMultiMatchQuery(\"this is a test\", \"subject\", \"message\").Type(\"phrase_prefix\").TieBreaker(0)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[\"subject\",\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0,\"type\":\"phrase_prefix\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiMatchQueryBestFieldsWithCustomTieBreaker(t *testing.T) {\n\tq := NewMultiMatchQuery(\"this is a test\", \"subject\", \"message\").\n\t\tType(\"best_fields\").\n\t\tTieBreaker(0.3)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[\"subject\",\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0.3,\"type\":\"best_fields\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiMatchQueryBoolPrefix(t *testing.T) {\n\tq := NewMultiMatchQuery(\"this is a test\", \"subject\", \"message\").Type(\"bool_prefix\").TieBreaker(1)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[\"subject\",\"message\"],\"query\":\"this is a test\",\"tie_breaker\":1,\"type\":\"bool_prefix\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestMultiMatchQueryOptions(t *testing.T) {\n\ttests := []struct {\n\t\tQuery *MultiMatchQuery\n\t\tWant  string\n\t}{\n\t\t{\n\t\t\tQuery: NewMultiMatchQuery(\"this is a test\", \"message\"),\n\t\t\tWant:  `{\"multi_match\":{\"fields\":[\"message\"],\"query\":\"this is a test\"}}`,\n\t\t},\n\t\t{\n\t\t\tQuery: NewMultiMatchQuery(\"this is a test\", \"message\").Type(\"best_fields\").TieBreaker(0),\n\t\t\tWant:  `{\"multi_match\":{\"fields\":[\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0,\"type\":\"best_fields\"}}`,\n\t\t},\n\t\t{\n\t\t\tQuery: NewMultiMatchQuery(\"this is a test\", \"message\").Type(\"best_fields\").TieBreaker(0.5),\n\t\t\tWant:  `{\"multi_match\":{\"fields\":[\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0.5,\"type\":\"best_fields\"}}`,\n\t\t},\n\t\t{\n\t\t\tQuery: NewMultiMatchQuery(\"this is a test\", \"message\").TieBreaker(0.5).Type(\"best_fields\"),\n\t\t\tWant:  `{\"multi_match\":{\"fields\":[\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0.5,\"type\":\"best_fields\"}}`,\n\t\t},\n\t\t{\n\t\t\tQuery: NewMultiMatchQuery(\"this is a test\", \"message\").Type(\"cross_fields\").TieBreaker(0.5),\n\t\t\tWant:  `{\"multi_match\":{\"fields\":[\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0.5,\"type\":\"cross_fields\"}}`,\n\t\t},\n\t\t{\n\t\t\tQuery: NewMultiMatchQuery(\"this is a test\", \"message\").TieBreaker(0.5).Type(\"cross_fields\"),\n\t\t\tWant:  `{\"multi_match\":{\"fields\":[\"message\"],\"query\":\"this is a test\",\"tie_breaker\":0.5,\"type\":\"cross_fields\"}}`,\n\t\t},\n\t}\n\tfor i, tt := range tests {\n\t\tsrc, err := tt.Query.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: %v\", i, err)\n\t\t}\n\t\tdata, err := json.Marshal(src)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: marshaling to JSON failed: %v\", i, err)\n\t\t}\n\t\tif want, have := tt.Want, string(data); want != have {\n\t\t\tt.Errorf(\"#%d: want\\n%s\\n, have:\\n%s\", i, want, have)\n\t\t}\n\t}\n}\n\nfunc TestMultiMatchQueryDefaultTieBreaker(t *testing.T) {\n\t// should not add tie_breaker field within the query DSL unless specified\n\tq := NewMultiMatchQuery(\"this is a test\", \"subject\", \"message\").Type(\"bool_prefix\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"multi_match\":{\"fields\":[\"subject\",\"message\"],\"query\":\"this is a test\",\"type\":\"bool_prefix\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_nested.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// NestedQuery allows to query nested objects / docs.\n// The query is executed against the nested objects / docs as if they were\n// indexed as separate docs (they are, internally) and resulting in the\n// root parent doc (or parent nested mapping).\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-nested-query.html\ntype NestedQuery struct {\n\tquery          Query\n\tpath           string\n\tscoreMode      string\n\tboost          *float64\n\tqueryName      string\n\tinnerHit       *InnerHit\n\tignoreUnmapped *bool\n}\n\n// NewNestedQuery creates and initializes a new NestedQuery.\nfunc NewNestedQuery(path string, query Query) *NestedQuery {\n\treturn &NestedQuery{path: path, query: query}\n}\n\n// ScoreMode specifies the score mode.\nfunc (q *NestedQuery) ScoreMode(scoreMode string) *NestedQuery {\n\tq.scoreMode = scoreMode\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *NestedQuery) Boost(boost float64) *NestedQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used\n// when searching for matched_filters per hit\nfunc (q *NestedQuery) QueryName(queryName string) *NestedQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// InnerHit sets the inner hit definition in the scope of this nested query\n// and reusing the defined path and query.\nfunc (q *NestedQuery) InnerHit(innerHit *InnerHit) *NestedQuery {\n\tq.innerHit = innerHit\n\treturn q\n}\n\n// IgnoreUnmapped sets the ignore_unmapped option for the filter that ignores\n// unmapped nested fields\nfunc (q *NestedQuery) IgnoreUnmapped(value bool) *NestedQuery {\n\tq.ignoreUnmapped = &value\n\treturn q\n}\n\n// Source returns JSON for the query.\nfunc (q *NestedQuery) Source() (interface{}, error) {\n\tquery := make(map[string]interface{})\n\tnq := make(map[string]interface{})\n\tquery[\"nested\"] = nq\n\n\tsrc, err := q.query.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tnq[\"query\"] = src\n\n\tnq[\"path\"] = q.path\n\n\tif q.scoreMode != \"\" {\n\t\tnq[\"score_mode\"] = q.scoreMode\n\t}\n\tif q.boost != nil {\n\t\tnq[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tnq[\"_name\"] = q.queryName\n\t}\n\tif q.ignoreUnmapped != nil {\n\t\tnq[\"ignore_unmapped\"] = *q.ignoreUnmapped\n\t}\n\tif q.innerHit != nil {\n\t\tsrc, err := q.innerHit.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tnq[\"inner_hits\"] = src\n\t}\n\treturn query, nil\n}\n"
  },
  {
    "path": "search_queries_nested_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestNestedQuery(t *testing.T) {\n\tbq := NewBoolQuery()\n\tbq = bq.Must(NewTermQuery(\"obj1.name\", \"blue\"))\n\tbq = bq.Must(NewRangeQuery(\"obj1.count\").Gt(5))\n\tq := NewNestedQuery(\"obj1\", bq).QueryName(\"qname\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"nested\":{\"_name\":\"qname\",\"path\":\"obj1\",\"query\":{\"bool\":{\"must\":[{\"term\":{\"obj1.name\":\"blue\"}},{\"range\":{\"obj1.count\":{\"from\":5,\"include_lower\":false,\"include_upper\":true,\"to\":null}}}]}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestNestedQueryWithInnerHit(t *testing.T) {\n\tbq := NewBoolQuery()\n\tbq = bq.Must(NewTermQuery(\"obj1.name\", \"blue\"))\n\tbq = bq.Must(NewRangeQuery(\"obj1.count\").Gt(5))\n\tq := NewNestedQuery(\"obj1\", bq)\n\tq = q.QueryName(\"qname\")\n\tq = q.InnerHit(NewInnerHit().Name(\"comments\").Query(NewTermQuery(\"user\", \"olivere\")))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"nested\":{\"_name\":\"qname\",\"inner_hits\":{\"name\":\"comments\",\"query\":{\"term\":{\"user\":\"olivere\"}}},\"path\":\"obj1\",\"query\":{\"bool\":{\"must\":[{\"term\":{\"obj1.name\":\"blue\"}},{\"range\":{\"obj1.count\":{\"from\":5,\"include_lower\":false,\"include_upper\":true,\"to\":null}}}]}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestNestedQueryWithIgnoreUnmapped(t *testing.T) {\n\tvar tests = []struct {\n\t\tquery    *BoolQuery\n\t\texpected string\n\t}{\n\t\t{\n\t\t\tNewBoolQuery().Must(NewNestedQuery(\"path\", NewTermQuery(\"test\", \"test\"))),\n\t\t\t`{\"bool\":{\"must\":{\"nested\":{\"path\":\"path\",\"query\":{\"term\":{\"test\":\"test\"}}}}}}`,\n\t\t},\n\t\t{\n\t\t\tNewBoolQuery().Must(NewNestedQuery(\"path\", NewTermQuery(\"test\", \"test\")).IgnoreUnmapped(true)),\n\t\t\t`{\"bool\":{\"must\":{\"nested\":{\"ignore_unmapped\":true,\"path\":\"path\",\"query\":{\"term\":{\"test\":\"test\"}}}}}}`,\n\t\t},\n\t\t{\n\t\t\tNewBoolQuery().Must(NewNestedQuery(\"path\", NewTermQuery(\"test\", \"test\")).IgnoreUnmapped(false)),\n\t\t\t`{\"bool\":{\"must\":{\"nested\":{\"ignore_unmapped\":false,\"path\":\"path\",\"query\":{\"term\":{\"test\":\"test\"}}}}}}`,\n\t\t},\n\t}\n\tfor _, test := range tests {\n\t\tsrc, err := test.query.Source()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tdata, err := json.Marshal(src)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t\t}\n\t\tgot := string(data)\n\t\tif got != test.expected {\n\t\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", test.expected, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "search_queries_parent_id.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// ParentIdQuery can be used to find child documents which belong to a\n// particular parent. Given the following mapping definition.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-parent-id-query.html\ntype ParentIdQuery struct {\n\ttyp            string\n\tid             string\n\tignoreUnmapped *bool\n\tboost          *float64\n\tqueryName      string\n\tinnerHit       *InnerHit\n}\n\n// NewParentIdQuery creates and initializes a new parent_id query.\nfunc NewParentIdQuery(typ, id string) *ParentIdQuery {\n\treturn &ParentIdQuery{\n\t\ttyp: typ,\n\t\tid:  id,\n\t}\n}\n\n// Type sets the parent type.\nfunc (q *ParentIdQuery) Type(typ string) *ParentIdQuery {\n\tq.typ = typ\n\treturn q\n}\n\n// Id sets the id.\nfunc (q *ParentIdQuery) Id(id string) *ParentIdQuery {\n\tq.id = id\n\treturn q\n}\n\n// IgnoreUnmapped specifies whether unmapped types should be ignored.\n// If set to false, the query failes when an unmapped type is found.\nfunc (q *ParentIdQuery) IgnoreUnmapped(ignore bool) *ParentIdQuery {\n\tq.ignoreUnmapped = &ignore\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *ParentIdQuery) Boost(boost float64) *ParentIdQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName specifies the query name for the filter that can be used when\n// searching for matched filters per hit.\nfunc (q *ParentIdQuery) QueryName(queryName string) *ParentIdQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// InnerHit sets the inner hit definition in the scope of this query and\n// reusing the defined type and query.\nfunc (q *ParentIdQuery) InnerHit(innerHit *InnerHit) *ParentIdQuery {\n\tq.innerHit = innerHit\n\treturn q\n}\n\n// Source returns JSON for the parent_id query.\nfunc (q *ParentIdQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"parent_id\" : {\n\t//       \"type\" : \"blog\",\n\t//       \"id\" : \"1\"\n\t//   }\n\t// }\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"parent_id\"] = query\n\n\tquery[\"type\"] = q.typ\n\tquery[\"id\"] = q.id\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.ignoreUnmapped != nil {\n\t\tquery[\"ignore_unmapped\"] = *q.ignoreUnmapped\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\tif q.innerHit != nil {\n\t\tsrc, err := q.innerHit.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tquery[\"inner_hits\"] = src\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_parent_id_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestParentIdQueryTest(t *testing.T) {\n\ttests := []struct {\n\t\tQuery    Query\n\t\tExpected string\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tQuery:    NewParentIdQuery(\"blog_tag\", \"1\"),\n\t\t\tExpected: `{\"parent_id\":{\"id\":\"1\",\"type\":\"blog_tag\"}}`,\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tQuery:    NewParentIdQuery(\"blog_tag\", \"1\").IgnoreUnmapped(true),\n\t\t\tExpected: `{\"parent_id\":{\"id\":\"1\",\"ignore_unmapped\":true,\"type\":\"blog_tag\"}}`,\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tQuery:    NewParentIdQuery(\"blog_tag\", \"1\").IgnoreUnmapped(false),\n\t\t\tExpected: `{\"parent_id\":{\"id\":\"1\",\"ignore_unmapped\":false,\"type\":\"blog_tag\"}}`,\n\t\t},\n\t\t// #3\n\t\t{\n\t\t\tQuery:    NewParentIdQuery(\"blog_tag\", \"1\").IgnoreUnmapped(true).Boost(5).QueryName(\"my_parent_query\"),\n\t\t\tExpected: `{\"parent_id\":{\"_name\":\"my_parent_query\",\"boost\":5,\"id\":\"1\",\"ignore_unmapped\":true,\"type\":\"blog_tag\"}}`,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tsrc, err := tt.Query.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: encoding Source failed: %v\", i, err)\n\t\t}\n\t\tdata, err := json.Marshal(src)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: marshaling to JSON failed: %v\", i, err)\n\t\t}\n\t\tif want, got := tt.Expected, string(data); want != got {\n\t\t\tt.Fatalf(\"#%d: expected\\n%s\\ngot:\\n%s\", i, want, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "search_queries_percolator.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"errors\"\n\n// PercolatorQuery can be used to match queries stored in an index.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-percolate-query.html\ntype PercolatorQuery struct {\n\tfield                     string\n\tname                      string\n\tdocumentType              string // deprecated\n\tdocuments                 []interface{}\n\tindexedDocumentIndex      string\n\tindexedDocumentType       string\n\tindexedDocumentId         string\n\tindexedDocumentRouting    string\n\tindexedDocumentPreference string\n\tindexedDocumentVersion    *int64\n}\n\n// NewPercolatorQuery creates and initializes a new Percolator query.\nfunc NewPercolatorQuery() *PercolatorQuery {\n\treturn &PercolatorQuery{}\n}\n\nfunc (q *PercolatorQuery) Field(field string) *PercolatorQuery {\n\tq.field = field\n\treturn q\n}\n\n// Name used for identification purposes in \"_percolator_document_slot\" response\n// field when multiple percolate queries have been specified in the main query.\nfunc (q *PercolatorQuery) Name(name string) *PercolatorQuery {\n\tq.name = name\n\treturn q\n}\n\n// Deprecated: DocumentType is deprecated as of 6.0.\nfunc (q *PercolatorQuery) DocumentType(typ string) *PercolatorQuery {\n\tq.documentType = typ\n\treturn q\n}\n\nfunc (q *PercolatorQuery) Document(docs ...interface{}) *PercolatorQuery {\n\tq.documents = append(q.documents, docs...)\n\treturn q\n}\n\nfunc (q *PercolatorQuery) IndexedDocumentIndex(index string) *PercolatorQuery {\n\tq.indexedDocumentIndex = index\n\treturn q\n}\n\nfunc (q *PercolatorQuery) IndexedDocumentType(typ string) *PercolatorQuery {\n\tq.indexedDocumentType = typ\n\treturn q\n}\n\nfunc (q *PercolatorQuery) IndexedDocumentId(id string) *PercolatorQuery {\n\tq.indexedDocumentId = id\n\treturn q\n}\n\nfunc (q *PercolatorQuery) IndexedDocumentRouting(routing string) *PercolatorQuery {\n\tq.indexedDocumentRouting = routing\n\treturn q\n}\n\nfunc (q *PercolatorQuery) IndexedDocumentPreference(preference string) *PercolatorQuery {\n\tq.indexedDocumentPreference = preference\n\treturn q\n}\n\nfunc (q *PercolatorQuery) IndexedDocumentVersion(version int64) *PercolatorQuery {\n\tq.indexedDocumentVersion = &version\n\treturn q\n}\n\n// Source returns JSON for the percolate query.\nfunc (q *PercolatorQuery) Source() (interface{}, error) {\n\tif len(q.field) == 0 {\n\t\treturn nil, errors.New(\"elastic: Field is required in PercolatorQuery\")\n\t}\n\n\t// {\n\t//   \"percolate\" : { ... }\n\t// }\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"percolate\"] = params\n\tparams[\"field\"] = q.field\n\tif q.documentType != \"\" {\n\t\tparams[\"document_type\"] = q.documentType\n\t}\n\tif q.name != \"\" {\n\t\tparams[\"name\"] = q.name\n\t}\n\n\tswitch len(q.documents) {\n\tcase 0:\n\tcase 1:\n\t\tparams[\"document\"] = q.documents[0]\n\tdefault:\n\t\tparams[\"documents\"] = q.documents\n\t}\n\n\tif s := q.indexedDocumentIndex; s != \"\" {\n\t\tparams[\"index\"] = s\n\t}\n\tif s := q.indexedDocumentType; s != \"\" {\n\t\tparams[\"type\"] = s\n\t}\n\tif s := q.indexedDocumentId; s != \"\" {\n\t\tparams[\"id\"] = s\n\t}\n\tif s := q.indexedDocumentRouting; s != \"\" {\n\t\tparams[\"routing\"] = s\n\t}\n\tif s := q.indexedDocumentPreference; s != \"\" {\n\t\tparams[\"preference\"] = s\n\t}\n\tif v := q.indexedDocumentVersion; v != nil {\n\t\tparams[\"version\"] = *v\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_percolator_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestPercolatorQuery(t *testing.T) {\n\tq := NewPercolatorQuery().\n\t\tField(\"query\").\n\t\tDocument(map[string]interface{}{\n\t\t\t\"message\": \"A new bonsai tree in the office\",\n\t\t})\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percolate\":{\"document\":{\"message\":\"A new bonsai tree in the office\"},\"field\":\"query\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercolatorQueryWithMultipleDocuments(t *testing.T) {\n\tq := NewPercolatorQuery().\n\t\tField(\"query\").\n\t\tDocument(\n\t\t\tmap[string]interface{}{\n\t\t\t\t\"message\": \"bonsai tree\",\n\t\t\t}, map[string]interface{}{\n\t\t\t\t\"message\": \"new tree\",\n\t\t\t},\n\t\t)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percolate\":{\"documents\":[{\"message\":\"bonsai tree\"},{\"message\":\"new tree\"}],\"field\":\"query\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercolatorQueryWithExistingDocument(t *testing.T) {\n\tq := NewPercolatorQuery().\n\t\tField(\"query\").\n\t\tIndexedDocumentIndex(\"my-index\").\n\t\tIndexedDocumentType(\"_doc\").\n\t\tIndexedDocumentId(\"2\").\n\t\tIndexedDocumentVersion(1)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percolate\":{\"field\":\"query\",\"id\":\"2\",\"index\":\"my-index\",\"type\":\"_doc\",\"version\":1}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercolatorQueryWithDetails(t *testing.T) {\n\tq := NewPercolatorQuery().\n\t\tField(\"query\").\n\t\tDocument(map[string]interface{}{\n\t\t\t\"message\": \"A new bonsai tree in the office\",\n\t\t}).\n\t\tIndexedDocumentIndex(\"index\").\n\t\tIndexedDocumentId(\"1\").\n\t\tIndexedDocumentRouting(\"route\").\n\t\tIndexedDocumentPreference(\"one\").\n\t\tIndexedDocumentVersion(1)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"percolate\":{\"document\":{\"message\":\"A new bonsai tree in the office\"},\"field\":\"query\",\"id\":\"1\",\"index\":\"index\",\"preference\":\"one\",\"routing\":\"route\",\"version\":1}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPercolatorQueryWithMissingFields(t *testing.T) {\n\tq := NewPercolatorQuery() // no Field, Document, or Query\n\t_, err := q.Source()\n\tif err == nil {\n\t\tt.Fatal(\"expected error, got nil\")\n\t}\n}\n"
  },
  {
    "path": "search_queries_pinned.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// PinnedQuery is a query that promotes selected documents to rank higher than those matching a given query.\n//\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.8/query-dsl-pinned-query.html\ntype PinnedQuery struct {\n\tids     []string\n\torganic Query\n}\n\n// NewPinnedQuery creates and initializes a new pinned query.\nfunc NewPinnedQuery() *PinnedQuery {\n\treturn &PinnedQuery{}\n}\n\n// Ids sets an array of document IDs listed in the order they are to appear in results.\nfunc (q *PinnedQuery) Ids(ids ...string) *PinnedQuery {\n\tq.ids = ids\n\treturn q\n}\n\n// Organic sets a choice of query used to rank documents which will be ranked below the \"pinned\" document ids.\nfunc (q *PinnedQuery) Organic(query Query) *PinnedQuery {\n\tq.organic = query\n\treturn q\n}\n\n// Source returns the JSON serializable content for this query.\nfunc (q *PinnedQuery) Source() (interface{}, error) {\n\t// {\n\t// \t  \"pinned\": {\n\t// \t  \t\"ids\": [ \"1\", \"4\", \"100\" ],\n\t// \t  \t\"organic\": {\n\t// \t\t  \"match\": {\n\t// \t\t    \"description\": \"iphone\"\n\t// \t\t  }\n\t// \t\t}\n\t//    }\n\t// }\n\n\tquery := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tquery[\"pinned\"] = params\n\tif len(q.ids) > 0 {\n\t\tparams[\"ids\"] = q.ids\n\t}\n\tif q.organic != nil {\n\t\tsrc, err := q.organic.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tparams[\"organic\"] = src\n\t}\n\n\treturn query, nil\n}\n"
  },
  {
    "path": "search_queries_pinned_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestPinnedQueryTest(t *testing.T) {\n\ttests := []struct {\n\t\tQuery    Query\n\t\tExpected string\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tQuery:    NewPinnedQuery(),\n\t\t\tExpected: `{\"pinned\":{}}`,\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tQuery:    NewPinnedQuery().Ids(\"1\", \"2\", \"3\"),\n\t\t\tExpected: `{\"pinned\":{\"ids\":[\"1\",\"2\",\"3\"]}}`,\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tQuery:    NewPinnedQuery().Organic(NewMatchAllQuery()),\n\t\t\tExpected: `{\"pinned\":{\"organic\":{\"match_all\":{}}}}`,\n\t\t},\n\t\t// #3\n\t\t{\n\t\t\tQuery:    NewPinnedQuery().Ids(\"1\", \"2\", \"3\").Organic(NewMatchAllQuery()),\n\t\t\tExpected: `{\"pinned\":{\"ids\":[\"1\",\"2\",\"3\"],\"organic\":{\"match_all\":{}}}}`,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tsrc, err := tt.Query.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: encoding Source failed: %v\", i, err)\n\t\t}\n\t\tdata, err := json.Marshal(src)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: marshaling to JSON failed: %v\", i, err)\n\t\t}\n\t\tif want, got := tt.Expected, string(data); want != got {\n\t\t\tt.Fatalf(\"#%d: expected\\n%s\\ngot:\\n%s\", i, want, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "search_queries_prefix.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// PrefixQuery matches documents that have fields containing terms\n// with a specified prefix (not analyzed).\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-prefix-query.html\ntype PrefixQuery struct {\n\tname            string\n\tprefix          string\n\tboost           *float64\n\trewrite         string\n\tcaseInsensitive *bool\n\tqueryName       string\n}\n\n// NewPrefixQuery creates and initializes a new PrefixQuery.\nfunc NewPrefixQuery(name string, prefix string) *PrefixQuery {\n\treturn &PrefixQuery{name: name, prefix: prefix}\n}\n\n// Boost sets the boost for this query.\nfunc (q *PrefixQuery) Boost(boost float64) *PrefixQuery {\n\tq.boost = &boost\n\treturn q\n}\n\nfunc (q *PrefixQuery) Rewrite(rewrite string) *PrefixQuery {\n\tq.rewrite = rewrite\n\treturn q\n}\n\nfunc (q *PrefixQuery) CaseInsensitive(caseInsensitive bool) *PrefixQuery {\n\tq.caseInsensitive = &caseInsensitive\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched_filters per hit.\nfunc (q *PrefixQuery) QueryName(queryName string) *PrefixQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the query.\nfunc (q *PrefixQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"prefix\"] = query\n\n\tif q.boost == nil && q.rewrite == \"\" && q.queryName == \"\" && q.caseInsensitive == nil {\n\t\tquery[q.name] = q.prefix\n\t} else {\n\t\tsubQuery := make(map[string]interface{})\n\t\tsubQuery[\"value\"] = q.prefix\n\t\tif q.boost != nil {\n\t\t\tsubQuery[\"boost\"] = *q.boost\n\t\t}\n\t\tif q.rewrite != \"\" {\n\t\t\tsubQuery[\"rewrite\"] = q.rewrite\n\t\t}\n\t\tif q.caseInsensitive != nil {\n\t\t\tsubQuery[\"case_insensitive\"] = *q.caseInsensitive\n\t\t}\n\t\tif q.queryName != \"\" {\n\t\t\tsubQuery[\"_name\"] = q.queryName\n\t\t}\n\t\tquery[q.name] = subQuery\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_prefix_example_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic_test\n\nimport (\n\t\"context\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc ExamplePrefixQuery() {\n\t// Get a client to the local Elasticsearch instance.\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\n\t// Define wildcard query\n\tq := elastic.NewPrefixQuery(\"user\", \"oli\")\n\tq = q.QueryName(\"my_query_name\")\n\n\tsearchResult, err := client.Search().\n\t\tIndex(\"twitter\").\n\t\tQuery(q).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\t_ = searchResult\n}\n"
  },
  {
    "path": "search_queries_prefix_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestPrefixQuery(t *testing.T) {\n\tq := NewPrefixQuery(\"user\", \"ki\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"prefix\":{\"user\":\"ki\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPrefixQueryWithCaseInsensitive(t *testing.T) {\n\tq := NewPrefixQuery(\"user\", \"ki\").CaseInsensitive(true)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"prefix\":{\"user\":{\"case_insensitive\":true,\"value\":\"ki\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPrefixQueryWithOptions(t *testing.T) {\n\tq := NewPrefixQuery(\"user\", \"ki\").CaseInsensitive(true)\n\tq = q.QueryName(\"my_query_name\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"prefix\":{\"user\":{\"_name\":\"my_query_name\",\"case_insensitive\":true,\"value\":\"ki\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_query_string.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"fmt\"\n)\n\n// QueryStringQuery uses the query parser in order to parse its content.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-query-string-query.html\ntype QueryStringQuery struct {\n\tqueryString              string\n\tdefaultField             string\n\tdefaultOperator          string\n\tanalyzer                 string\n\tquoteAnalyzer            string\n\tquoteFieldSuffix         string\n\tallowLeadingWildcard     *bool\n\tlowercaseExpandedTerms   *bool // Deprecated: Decision is now made by the analyzer\n\tenablePositionIncrements *bool\n\tanalyzeWildcard          *bool\n\tlocale                   string // Deprecated: Decision is now made by the analyzer\n\tboost                    *float64\n\tfuzziness                string\n\tfuzzyPrefixLength        *int\n\tfuzzyMaxExpansions       *int\n\tfuzzyRewrite             string\n\tphraseSlop               *int\n\tfields                   []string\n\tfieldBoosts              map[string]*float64\n\ttieBreaker               *float64\n\trewrite                  string\n\tminimumShouldMatch       string\n\tlenient                  *bool\n\tqueryName                string\n\ttimeZone                 string\n\tmaxDeterminizedStates    *int\n\tescape                   *bool\n\ttyp                      string\n}\n\n// NewQueryStringQuery creates and initializes a new QueryStringQuery.\nfunc NewQueryStringQuery(queryString string) *QueryStringQuery {\n\treturn &QueryStringQuery{\n\t\tqueryString: queryString,\n\t\tfields:      make([]string, 0),\n\t\tfieldBoosts: make(map[string]*float64),\n\t}\n}\n\n// DefaultField specifies the field to run against when no prefix field\n// is specified. Only relevant when not explicitly adding fields the query\n// string will run against.\nfunc (q *QueryStringQuery) DefaultField(defaultField string) *QueryStringQuery {\n\tq.defaultField = defaultField\n\treturn q\n}\n\n// Field adds a field to run the query string against.\nfunc (q *QueryStringQuery) Field(field string) *QueryStringQuery {\n\tq.fields = append(q.fields, field)\n\treturn q\n}\n\n// Type sets how multiple fields should be combined to build textual part queries,\n// e.g. \"best_fields\".\nfunc (q *QueryStringQuery) Type(typ string) *QueryStringQuery {\n\tq.typ = typ\n\treturn q\n}\n\n// FieldWithBoost adds a field to run the query string against with a specific boost.\nfunc (q *QueryStringQuery) FieldWithBoost(field string, boost float64) *QueryStringQuery {\n\tq.fields = append(q.fields, field)\n\tq.fieldBoosts[field] = &boost\n\treturn q\n}\n\n// TieBreaker is used when more than one field is used with the query string,\n// and combined queries are using dismax.\nfunc (q *QueryStringQuery) TieBreaker(tieBreaker float64) *QueryStringQuery {\n\tq.tieBreaker = &tieBreaker\n\treturn q\n}\n\n// DefaultOperator sets the boolean operator of the query parser used to\n// parse the query string.\n//\n// In default mode (OR) terms without any modifiers\n// are considered optional, e.g. \"capital of Hungary\" is equal to\n// \"capital OR of OR Hungary\".\n//\n// In AND mode, terms are considered to be in conjunction. The above mentioned\n// query is then parsed as \"capital AND of AND Hungary\".\nfunc (q *QueryStringQuery) DefaultOperator(operator string) *QueryStringQuery {\n\tq.defaultOperator = operator\n\treturn q\n}\n\n// Analyzer is an optional analyzer used to analyze the query string.\n// Note, if a field has search analyzer defined for it, then it will be used\n// automatically. Defaults to the smart search analyzer.\nfunc (q *QueryStringQuery) Analyzer(analyzer string) *QueryStringQuery {\n\tq.analyzer = analyzer\n\treturn q\n}\n\n// QuoteAnalyzer is an optional analyzer to be used to analyze the query string\n// for phrase searches. Note, if a field has search analyzer defined for it,\n// then it will be used automatically. Defaults to the smart search analyzer.\nfunc (q *QueryStringQuery) QuoteAnalyzer(quoteAnalyzer string) *QueryStringQuery {\n\tq.quoteAnalyzer = quoteAnalyzer\n\treturn q\n}\n\n// MaxDeterminizedState protects against too-difficult regular expression queries.\nfunc (q *QueryStringQuery) MaxDeterminizedState(maxDeterminizedStates int) *QueryStringQuery {\n\tq.maxDeterminizedStates = &maxDeterminizedStates\n\treturn q\n}\n\n// AllowLeadingWildcard specifies whether leading wildcards should be allowed\n// or not (defaults to true).\nfunc (q *QueryStringQuery) AllowLeadingWildcard(allowLeadingWildcard bool) *QueryStringQuery {\n\tq.allowLeadingWildcard = &allowLeadingWildcard\n\treturn q\n}\n\n// LowercaseExpandedTerms indicates whether terms of wildcard, prefix, fuzzy\n// and range queries are automatically lower-cased or not. Default is true.\n//\n// Deprecated: Decision is now made by the analyzer.\nfunc (q *QueryStringQuery) LowercaseExpandedTerms(lowercaseExpandedTerms bool) *QueryStringQuery {\n\tq.lowercaseExpandedTerms = &lowercaseExpandedTerms\n\treturn q\n}\n\n// EnablePositionIncrements indicates whether to enable position increments\n// in result query. Defaults to true.\n//\n// When set, result phrase and multi-phrase queries will be aware of position\n// increments. Useful when e.g. a StopFilter increases the position increment\n// of the token that follows an omitted token.\nfunc (q *QueryStringQuery) EnablePositionIncrements(enablePositionIncrements bool) *QueryStringQuery {\n\tq.enablePositionIncrements = &enablePositionIncrements\n\treturn q\n}\n\n// Fuzziness sets the edit distance for fuzzy queries. Default is \"AUTO\".\nfunc (q *QueryStringQuery) Fuzziness(fuzziness string) *QueryStringQuery {\n\tq.fuzziness = fuzziness\n\treturn q\n}\n\n// FuzzyPrefixLength sets the minimum prefix length for fuzzy queries.\n// Default is 1.\nfunc (q *QueryStringQuery) FuzzyPrefixLength(fuzzyPrefixLength int) *QueryStringQuery {\n\tq.fuzzyPrefixLength = &fuzzyPrefixLength\n\treturn q\n}\n\nfunc (q *QueryStringQuery) FuzzyMaxExpansions(fuzzyMaxExpansions int) *QueryStringQuery {\n\tq.fuzzyMaxExpansions = &fuzzyMaxExpansions\n\treturn q\n}\n\nfunc (q *QueryStringQuery) FuzzyRewrite(fuzzyRewrite string) *QueryStringQuery {\n\tq.fuzzyRewrite = fuzzyRewrite\n\treturn q\n}\n\n// PhraseSlop sets the default slop for phrases. If zero, then exact matches\n// are required. Default value is zero.\nfunc (q *QueryStringQuery) PhraseSlop(phraseSlop int) *QueryStringQuery {\n\tq.phraseSlop = &phraseSlop\n\treturn q\n}\n\n// AnalyzeWildcard indicates whether to enabled analysis on wildcard and prefix queries.\nfunc (q *QueryStringQuery) AnalyzeWildcard(analyzeWildcard bool) *QueryStringQuery {\n\tq.analyzeWildcard = &analyzeWildcard\n\treturn q\n}\n\nfunc (q *QueryStringQuery) Rewrite(rewrite string) *QueryStringQuery {\n\tq.rewrite = rewrite\n\treturn q\n}\n\nfunc (q *QueryStringQuery) MinimumShouldMatch(minimumShouldMatch string) *QueryStringQuery {\n\tq.minimumShouldMatch = minimumShouldMatch\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *QueryStringQuery) Boost(boost float64) *QueryStringQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QuoteFieldSuffix is an optional field name suffix to automatically\n// try and add to the field searched when using quoted text.\nfunc (q *QueryStringQuery) QuoteFieldSuffix(quoteFieldSuffix string) *QueryStringQuery {\n\tq.quoteFieldSuffix = quoteFieldSuffix\n\treturn q\n}\n\n// Lenient indicates whether the query string parser should be lenient\n// when parsing field values. It defaults to the index setting and if not\n// set, defaults to false.\nfunc (q *QueryStringQuery) Lenient(lenient bool) *QueryStringQuery {\n\tq.lenient = &lenient\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched_filters per hit.\nfunc (q *QueryStringQuery) QueryName(queryName string) *QueryStringQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Locale specifies the locale to be used for string conversions.\n//\n// Deprecated: Decision is now made by the analyzer.\nfunc (q *QueryStringQuery) Locale(locale string) *QueryStringQuery {\n\tq.locale = locale\n\treturn q\n}\n\n// TimeZone can be used to automatically adjust to/from fields using a\n// timezone. Only used with date fields, of course.\nfunc (q *QueryStringQuery) TimeZone(timeZone string) *QueryStringQuery {\n\tq.timeZone = timeZone\n\treturn q\n}\n\n// Escape performs escaping of the query string.\nfunc (q *QueryStringQuery) Escape(escape bool) *QueryStringQuery {\n\tq.escape = &escape\n\treturn q\n}\n\n// Source returns JSON for the query.\nfunc (q *QueryStringQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"query_string\"] = query\n\n\tquery[\"query\"] = q.queryString\n\n\tif q.defaultField != \"\" {\n\t\tquery[\"default_field\"] = q.defaultField\n\t}\n\n\tif len(q.fields) > 0 {\n\t\tvar fields []string\n\t\tfor _, field := range q.fields {\n\t\t\tif boost, found := q.fieldBoosts[field]; found {\n\t\t\t\tif boost != nil {\n\t\t\t\t\tfields = append(fields, fmt.Sprintf(\"%s^%f\", field, *boost))\n\t\t\t\t} else {\n\t\t\t\t\tfields = append(fields, field)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfields = append(fields, field)\n\t\t\t}\n\t\t}\n\t\tquery[\"fields\"] = fields\n\t}\n\n\tif q.tieBreaker != nil {\n\t\tquery[\"tie_breaker\"] = *q.tieBreaker\n\t}\n\tif q.defaultOperator != \"\" {\n\t\tquery[\"default_operator\"] = q.defaultOperator\n\t}\n\tif q.analyzer != \"\" {\n\t\tquery[\"analyzer\"] = q.analyzer\n\t}\n\tif q.quoteAnalyzer != \"\" {\n\t\tquery[\"quote_analyzer\"] = q.quoteAnalyzer\n\t}\n\tif q.maxDeterminizedStates != nil {\n\t\tquery[\"max_determinized_states\"] = *q.maxDeterminizedStates\n\t}\n\tif q.allowLeadingWildcard != nil {\n\t\tquery[\"allow_leading_wildcard\"] = *q.allowLeadingWildcard\n\t}\n\tif q.lowercaseExpandedTerms != nil {\n\t\tquery[\"lowercase_expanded_terms\"] = *q.lowercaseExpandedTerms\n\t}\n\tif q.enablePositionIncrements != nil {\n\t\tquery[\"enable_position_increments\"] = *q.enablePositionIncrements\n\t}\n\tif q.fuzziness != \"\" {\n\t\tquery[\"fuzziness\"] = q.fuzziness\n\t}\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif q.fuzzyPrefixLength != nil {\n\t\tquery[\"fuzzy_prefix_length\"] = *q.fuzzyPrefixLength\n\t}\n\tif q.fuzzyMaxExpansions != nil {\n\t\tquery[\"fuzzy_max_expansions\"] = *q.fuzzyMaxExpansions\n\t}\n\tif q.fuzzyRewrite != \"\" {\n\t\tquery[\"fuzzy_rewrite\"] = q.fuzzyRewrite\n\t}\n\tif q.phraseSlop != nil {\n\t\tquery[\"phrase_slop\"] = *q.phraseSlop\n\t}\n\tif q.analyzeWildcard != nil {\n\t\tquery[\"analyze_wildcard\"] = *q.analyzeWildcard\n\t}\n\tif q.rewrite != \"\" {\n\t\tquery[\"rewrite\"] = q.rewrite\n\t}\n\tif q.minimumShouldMatch != \"\" {\n\t\tquery[\"minimum_should_match\"] = q.minimumShouldMatch\n\t}\n\tif q.quoteFieldSuffix != \"\" {\n\t\tquery[\"quote_field_suffix\"] = q.quoteFieldSuffix\n\t}\n\tif q.lenient != nil {\n\t\tquery[\"lenient\"] = *q.lenient\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\tif q.locale != \"\" {\n\t\tquery[\"locale\"] = q.locale\n\t}\n\tif q.timeZone != \"\" {\n\t\tquery[\"time_zone\"] = q.timeZone\n\t}\n\tif q.escape != nil {\n\t\tquery[\"escape\"] = *q.escape\n\t}\n\tif q.typ != \"\" {\n\t\tquery[\"type\"] = q.typ\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_query_string_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestQueryStringQuery(t *testing.T) {\n\tq := NewQueryStringQuery(`this AND that OR thus`)\n\tq = q.DefaultField(\"content\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query_string\":{\"default_field\":\"content\",\"query\":\"this AND that OR thus\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestQueryStringQueryTimeZone(t *testing.T) {\n\tq := NewQueryStringQuery(`tweet_date:[2015-01-01 TO 2017-12-31]`)\n\tq = q.TimeZone(\"Europe/Berlin\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query_string\":{\"query\":\"tweet_date:[2015-01-01 TO 2017-12-31]\",\"time_zone\":\"Europe/Berlin\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestQueryStringQueryIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\tq := NewQueryStringQuery(\"Golang\")\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(q).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(1); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 1; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_range.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// RangeQuery matches documents with fields that have terms within a certain range.\n//\n// For details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-range-query.html\ntype RangeQuery struct {\n\tname         string\n\tfrom         interface{}\n\tto           interface{}\n\ttimeZone     string\n\tincludeLower bool\n\tincludeUpper bool\n\tboost        *float64\n\tqueryName    string\n\tformat       string\n\trelation     string\n}\n\n// NewRangeQuery creates and initializes a new RangeQuery.\nfunc NewRangeQuery(name string) *RangeQuery {\n\treturn &RangeQuery{name: name, includeLower: true, includeUpper: true}\n}\n\n// From indicates the from part of the RangeQuery.\n// Use nil to indicate an unbounded from part.\nfunc (q *RangeQuery) From(from interface{}) *RangeQuery {\n\tq.from = from\n\treturn q\n}\n\n// Gt indicates a greater-than value for the from part.\n// Use nil to indicate an unbounded from part.\nfunc (q *RangeQuery) Gt(from interface{}) *RangeQuery {\n\tq.from = from\n\tq.includeLower = false\n\treturn q\n}\n\n// Gte indicates a greater-than-or-equal value for the from part.\n// Use nil to indicate an unbounded from part.\nfunc (q *RangeQuery) Gte(from interface{}) *RangeQuery {\n\tq.from = from\n\tq.includeLower = true\n\treturn q\n}\n\n// To indicates the to part of the RangeQuery.\n// Use nil to indicate an unbounded to part.\nfunc (q *RangeQuery) To(to interface{}) *RangeQuery {\n\tq.to = to\n\treturn q\n}\n\n// Lt indicates a less-than value for the to part.\n// Use nil to indicate an unbounded to part.\nfunc (q *RangeQuery) Lt(to interface{}) *RangeQuery {\n\tq.to = to\n\tq.includeUpper = false\n\treturn q\n}\n\n// Lte indicates a less-than-or-equal value for the to part.\n// Use nil to indicate an unbounded to part.\nfunc (q *RangeQuery) Lte(to interface{}) *RangeQuery {\n\tq.to = to\n\tq.includeUpper = true\n\treturn q\n}\n\n// IncludeLower indicates whether the lower bound should be included or not.\n// Defaults to true.\nfunc (q *RangeQuery) IncludeLower(includeLower bool) *RangeQuery {\n\tq.includeLower = includeLower\n\treturn q\n}\n\n// IncludeUpper indicates whether the upper bound should be included or not.\n// Defaults to true.\nfunc (q *RangeQuery) IncludeUpper(includeUpper bool) *RangeQuery {\n\tq.includeUpper = includeUpper\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *RangeQuery) Boost(boost float64) *RangeQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched_filters per hit.\nfunc (q *RangeQuery) QueryName(queryName string) *RangeQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// TimeZone is used for date fields. In that case, we can adjust the\n// from/to fields using a timezone.\nfunc (q *RangeQuery) TimeZone(timeZone string) *RangeQuery {\n\tq.timeZone = timeZone\n\treturn q\n}\n\n// Format is used for date fields. In that case, we can set the format\n// to be used instead of the mapper format.\nfunc (q *RangeQuery) Format(format string) *RangeQuery {\n\tq.format = format\n\treturn q\n}\n\n// Relation is used for range fields. which can be one of\n// \"within\", \"contains\", \"intersects\" (default) and \"disjoint\".\nfunc (q *RangeQuery) Relation(relation string) *RangeQuery {\n\tq.relation = relation\n\treturn q\n}\n\n// Source returns JSON for the query.\nfunc (q *RangeQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\trangeQ := make(map[string]interface{})\n\tsource[\"range\"] = rangeQ\n\n\tparams := make(map[string]interface{})\n\trangeQ[q.name] = params\n\n\tparams[\"from\"] = q.from\n\tparams[\"to\"] = q.to\n\tif q.timeZone != \"\" {\n\t\tparams[\"time_zone\"] = q.timeZone\n\t}\n\tif q.format != \"\" {\n\t\tparams[\"format\"] = q.format\n\t}\n\tif q.relation != \"\" {\n\t\tparams[\"relation\"] = q.relation\n\t}\n\tif q.boost != nil {\n\t\tparams[\"boost\"] = *q.boost\n\t}\n\tparams[\"include_lower\"] = q.includeLower\n\tparams[\"include_upper\"] = q.includeUpper\n\n\tif q.queryName != \"\" {\n\t\trangeQ[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_range_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestRangeQuery(t *testing.T) {\n\tq := NewRangeQuery(\"postDate\").From(\"2010-03-01\").To(\"2010-04-01\").Boost(3).Relation(\"within\")\n\tq = q.QueryName(\"my_query\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"_name\":\"my_query\",\"postDate\":{\"boost\":3,\"from\":\"2010-03-01\",\"include_lower\":true,\"include_upper\":true,\"relation\":\"within\",\"to\":\"2010-04-01\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRangeQueryWithTimeZone(t *testing.T) {\n\tq := NewRangeQuery(\"born\").\n\t\tGte(\"2012-01-01\").\n\t\tLte(\"now\").\n\t\tTimeZone(\"+1:00\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"born\":{\"from\":\"2012-01-01\",\"include_lower\":true,\"include_upper\":true,\"time_zone\":\"+1:00\",\"to\":\"now\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRangeQueryWithFormat(t *testing.T) {\n\tq := NewRangeQuery(\"born\").\n\t\tGte(\"2012/01/01\").\n\t\tLte(\"now\").\n\t\tFormat(\"yyyy/MM/dd\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"range\":{\"born\":{\"format\":\"yyyy/MM/dd\",\"from\":\"2012/01/01\",\"include_lower\":true,\"include_upper\":true,\"to\":\"now\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_rank_feature.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// RankFeatureQuery boosts the relevance score of documents based on the\n// numeric value of a rank_feature or rank_features field.\n//\n// The RankFeatureQuery is typically used in the should clause of a BoolQuery\n// so its relevance scores are added to other scores from the BoolQuery.\n//\n// For more details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.14/query-dsl-rank-feature-query.html\ntype RankFeatureQuery struct {\n\tfield     string\n\tscoreFunc RankFeatureScoreFunction\n\tboost     *float64\n\tqueryName string\n}\n\n// NewRankFeatureQuery creates and initializes a new RankFeatureQuery.\nfunc NewRankFeatureQuery(field string) *RankFeatureQuery {\n\treturn &RankFeatureQuery{\n\t\tfield: field,\n\t}\n}\n\n// Field name.\nfunc (q *RankFeatureQuery) Field(field string) *RankFeatureQuery {\n\tq.field = field\n\treturn q\n}\n\n// ScoreFunction specifies the score function for the RankFeatureQuery.\nfunc (q *RankFeatureQuery) ScoreFunction(f RankFeatureScoreFunction) *RankFeatureQuery {\n\tq.scoreFunc = f\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *RankFeatureQuery) Boost(boost float64) *RankFeatureQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched_filters per hit.\nfunc (q *RankFeatureQuery) QueryName(queryName string) *RankFeatureQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns the JSON serializable content for this query.\nfunc (q *RankFeatureQuery) Source() (interface{}, error) {\n\t// {\n\t// \t  \"rank_feature\": {\n\t// \t  \t\"field\": \"pagerank\",\n\t// \t  \t\"saturation\": {\n\t// \t\t  \"pivot\": 8\n\t// \t\t}\n\t//    }\n\t// }\n\n\tquery := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tquery[\"rank_feature\"] = params\n\tparams[\"field\"] = q.field\n\tif q.scoreFunc != nil {\n\t\tsrc, err := q.scoreFunc.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tparams[q.scoreFunc.Name()] = src\n\t}\n\tif q.boost != nil {\n\t\tparams[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\n\treturn query, nil\n}\n\n// -- Score functions --\n\n// RankFeatureScoreFunction specifies the interface for score functions\n// in the context of a RankFeatureQuery.\ntype RankFeatureScoreFunction interface {\n\tName() string\n\tSource() (interface{}, error)\n}\n\n// -- Log score function --\n\n// RankFeatureLogScoreFunction represents a Logarithmic score function for a\n// RankFeatureQuery.\n//\n// See here for details:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.14/query-dsl-rank-feature-query.html#rank-feature-query-logarithm\ntype RankFeatureLogScoreFunction struct {\n\tscalingFactor float64\n}\n\n// NewRankFeatureLogScoreFunction returns a new RankFeatureLogScoreFunction\n// with the given scaling factor.\nfunc NewRankFeatureLogScoreFunction(scalingFactor float64) *RankFeatureLogScoreFunction {\n\treturn &RankFeatureLogScoreFunction{\n\t\tscalingFactor: scalingFactor,\n\t}\n}\n\n// Name of the score function.\nfunc (f *RankFeatureLogScoreFunction) Name() string { return \"log\" }\n\n// Source returns a serializable JSON object for building the query.\nfunc (f *RankFeatureLogScoreFunction) Source() (interface{}, error) {\n\treturn map[string]interface{}{\n\t\t\"scaling_factor\": f.scalingFactor,\n\t}, nil\n}\n\n// -- Saturation score function --\n\n// RankFeatureSaturationScoreFunction represents a Log score function for a\n// RankFeatureQuery.\n//\n// See here for details:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.14/query-dsl-rank-feature-query.html#rank-feature-query-saturation\ntype RankFeatureSaturationScoreFunction struct {\n\tpivot *float64\n}\n\n// NewRankFeatureSaturationScoreFunction initializes a new\n// RankFeatureSaturationScoreFunction.\nfunc NewRankFeatureSaturationScoreFunction() *RankFeatureSaturationScoreFunction {\n\treturn &RankFeatureSaturationScoreFunction{}\n}\n\n// Pivot specifies the pivot to use.\nfunc (f *RankFeatureSaturationScoreFunction) Pivot(pivot float64) *RankFeatureSaturationScoreFunction {\n\tf.pivot = &pivot\n\treturn f\n}\n\n// Name of the score function.\nfunc (f *RankFeatureSaturationScoreFunction) Name() string { return \"saturation\" }\n\n// Source returns a serializable JSON object for building the query.\nfunc (f *RankFeatureSaturationScoreFunction) Source() (interface{}, error) {\n\tm := make(map[string]interface{})\n\tif f.pivot != nil {\n\t\tm[\"pivot\"] = *f.pivot\n\t}\n\treturn m, nil\n}\n\n// -- Sigmoid score function --\n\n// RankFeatureSigmoidScoreFunction represents a Sigmoid score function for a\n// RankFeatureQuery.\n//\n// See here for details:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.14/query-dsl-rank-feature-query.html#rank-feature-query-sigmoid\ntype RankFeatureSigmoidScoreFunction struct {\n\tpivot    float64\n\texponent float64\n}\n\n// NewRankFeatureSigmoidScoreFunction returns a new RankFeatureSigmoidScoreFunction\n// with the given scaling factor.\nfunc NewRankFeatureSigmoidScoreFunction(pivot, exponent float64) *RankFeatureSigmoidScoreFunction {\n\treturn &RankFeatureSigmoidScoreFunction{\n\t\tpivot:    pivot,\n\t\texponent: exponent,\n\t}\n}\n\n// Name of the score function.\nfunc (f *RankFeatureSigmoidScoreFunction) Name() string { return \"sigmoid\" }\n\n// Source returns a serializable JSON object for building the query.\nfunc (f *RankFeatureSigmoidScoreFunction) Source() (interface{}, error) {\n\treturn map[string]interface{}{\n\t\t\"pivot\":    f.pivot,\n\t\t\"exponent\": f.exponent,\n\t}, nil\n}\n\n// -- Linear score function --\n\n// RankFeatureLinearScoreFunction represents a Linear score function for a\n// RankFeatureQuery.\n//\n// See here for details:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.14/query-dsl-rank-feature-query.html#rank-feature-query-linear\ntype RankFeatureLinearScoreFunction struct {\n}\n\n// NewRankFeatureLinearScoreFunction initializes a new\n// RankFeatureLinearScoreFunction.\nfunc NewRankFeatureLinearScoreFunction() *RankFeatureLinearScoreFunction {\n\treturn &RankFeatureLinearScoreFunction{}\n}\n\n// Name of the score function.\nfunc (f *RankFeatureLinearScoreFunction) Name() string { return \"linear\" }\n\n// Source returns a serializable JSON object for building the query.\nfunc (f *RankFeatureLinearScoreFunction) Source() (interface{}, error) {\n\treturn map[string]interface{}{}, nil\n}\n"
  },
  {
    "path": "search_queries_rank_feature_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestRankFeatureQueryTest(t *testing.T) {\n\ttests := []struct {\n\t\tQuery    Query\n\t\tExpected string\n\t}{\n\t\t// #0\n\t\t{\n\t\t\tQuery:    NewRankFeatureQuery(\"pagerank\"),\n\t\t\tExpected: `{\"rank_feature\":{\"field\":\"pagerank\"}}`,\n\t\t},\n\t\t// #1\n\t\t{\n\t\t\tQuery:    NewRankFeatureQuery(\"url_length\").Boost(0.1),\n\t\t\tExpected: `{\"rank_feature\":{\"boost\":0.1,\"field\":\"url_length\"}}`,\n\t\t},\n\t\t// #2\n\t\t{\n\t\t\tQuery:    NewRankFeatureQuery(\"pagerank\").ScoreFunction(NewRankFeatureSaturationScoreFunction().Pivot(8)),\n\t\t\tExpected: `{\"rank_feature\":{\"field\":\"pagerank\",\"saturation\":{\"pivot\":8}}}`,\n\t\t},\n\t\t// #3\n\t\t{\n\t\t\tQuery:    NewRankFeatureQuery(\"pagerank\").ScoreFunction(NewRankFeatureSaturationScoreFunction()),\n\t\t\tExpected: `{\"rank_feature\":{\"field\":\"pagerank\",\"saturation\":{}}}`,\n\t\t},\n\t\t// #4\n\t\t{\n\t\t\tQuery:    NewRankFeatureQuery(\"pagerank\").ScoreFunction(NewRankFeatureLogScoreFunction(4)),\n\t\t\tExpected: `{\"rank_feature\":{\"field\":\"pagerank\",\"log\":{\"scaling_factor\":4}}}`,\n\t\t},\n\t\t// #5\n\t\t{\n\t\t\tQuery:    NewRankFeatureQuery(\"pagerank\").ScoreFunction(NewRankFeatureSigmoidScoreFunction(7, 0.6)),\n\t\t\tExpected: `{\"rank_feature\":{\"field\":\"pagerank\",\"sigmoid\":{\"exponent\":0.6,\"pivot\":7}}}`,\n\t\t},\n\t\t// #6\n\t\t{\n\t\t\tQuery:    NewRankFeatureQuery(\"pagerank\").ScoreFunction(NewRankFeatureLinearScoreFunction()),\n\t\t\tExpected: `{\"rank_feature\":{\"field\":\"pagerank\",\"linear\":{}}}`,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tsrc, err := tt.Query.Source()\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: encoding Source failed: %v\", i, err)\n\t\t}\n\t\tdata, err := json.Marshal(src)\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"#%d: marshaling to JSON failed: %v\", i, err)\n\t\t}\n\t\tif want, got := tt.Expected, string(data); want != got {\n\t\t\tt.Fatalf(\"#%d: expected\\n%s\\ngot:\\n%s\", i, want, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "search_queries_raw_string.go",
    "content": "// Copyright 2012-present Oliver Eilhard, John Stanford. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"encoding/json\"\n\n// RawStringQuery can be used to treat a string representation of an ES query\n// as a Query.  Example usage:\n//    q := RawStringQuery(\"{\\\"match_all\\\":{}}\")\n//    db.Search().Query(q).From(1).Size(100).Do()\ntype RawStringQuery string\n\n// NewRawStringQuery ininitializes a new RawStringQuery.\n// It is the same as RawStringQuery(q).\nfunc NewRawStringQuery(q string) RawStringQuery {\n\treturn RawStringQuery(q)\n}\n\n// Source returns the JSON encoded body\nfunc (q RawStringQuery) Source() (interface{}, error) {\n\tvar f interface{}\n\terr := json.Unmarshal([]byte(q), &f)\n\treturn f, err\n}\n"
  },
  {
    "path": "search_queries_raw_string_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestRawStringQuery(t *testing.T) {\n\tq := RawStringQuery(`{\"match_all\":{}}`)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_all\":{}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestNewRawStringQuery(t *testing.T) {\n\tq := NewRawStringQuery(`{\"match_all\":{}}`)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"match_all\":{}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_regexp.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// RegexpQuery allows you to use regular expression term queries.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-regexp-query.html\ntype RegexpQuery struct {\n\tname                  string\n\tregexp                string\n\tflags                 string\n\tboost                 *float64\n\trewrite               string\n\tcaseInsensitive       *bool\n\tqueryName             string\n\tmaxDeterminizedStates *int\n}\n\n// NewRegexpQuery creates and initializes a new RegexpQuery.\nfunc NewRegexpQuery(name string, regexp string) *RegexpQuery {\n\treturn &RegexpQuery{name: name, regexp: regexp}\n}\n\n// Flags sets the regexp flags.\nfunc (q *RegexpQuery) Flags(flags string) *RegexpQuery {\n\tq.flags = flags\n\treturn q\n}\n\n// MaxDeterminizedStates protects against complex regular expressions.\nfunc (q *RegexpQuery) MaxDeterminizedStates(maxDeterminizedStates int) *RegexpQuery {\n\tq.maxDeterminizedStates = &maxDeterminizedStates\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *RegexpQuery) Boost(boost float64) *RegexpQuery {\n\tq.boost = &boost\n\treturn q\n}\n\nfunc (q *RegexpQuery) Rewrite(rewrite string) *RegexpQuery {\n\tq.rewrite = rewrite\n\treturn q\n}\n\nfunc (q *RegexpQuery) CaseInsensitive(caseInsensitive bool) *RegexpQuery {\n\tq.caseInsensitive = &caseInsensitive\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used\n// when searching for matched_filters per hit\nfunc (q *RegexpQuery) QueryName(queryName string) *RegexpQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns the JSON-serializable query data.\nfunc (q *RegexpQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"regexp\"] = query\n\n\tx := make(map[string]interface{})\n\tx[\"value\"] = q.regexp\n\tif q.flags != \"\" {\n\t\tx[\"flags\"] = q.flags\n\t}\n\tif q.maxDeterminizedStates != nil {\n\t\tx[\"max_determinized_states\"] = *q.maxDeterminizedStates\n\t}\n\tif q.boost != nil {\n\t\tx[\"boost\"] = *q.boost\n\t}\n\tif q.rewrite != \"\" {\n\t\tx[\"rewrite\"] = q.rewrite\n\t}\n\tif q.caseInsensitive != nil {\n\t\tx[\"case_insensitive\"] = *q.caseInsensitive\n\t}\n\tif q.queryName != \"\" {\n\t\tx[\"name\"] = q.queryName\n\t}\n\tquery[q.name] = x\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_regexp_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestRegexpQuery(t *testing.T) {\n\tq := NewRegexpQuery(\"name.first\", \"s.*y\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"regexp\":{\"name.first\":{\"value\":\"s.*y\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestRegexpQueryWithOptions(t *testing.T) {\n\tq := NewRegexpQuery(\"name.first\", \"s.*y\").\n\t\tBoost(1.2).\n\t\tFlags(\"INTERSECTION|COMPLEMENT|EMPTY\").\n\t\tCaseInsensitive(true).\n\t\tQueryName(\"my_query_name\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"regexp\":{\"name.first\":{\"boost\":1.2,\"case_insensitive\":true,\"flags\":\"INTERSECTION|COMPLEMENT|EMPTY\",\"name\":\"my_query_name\",\"value\":\"s.*y\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_script.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"errors\"\n\n// ScriptQuery allows to define scripts as filters.\n//\n// For details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-script-query.html\ntype ScriptQuery struct {\n\tscript    *Script\n\tqueryName string\n}\n\n// NewScriptQuery creates and initializes a new ScriptQuery.\nfunc NewScriptQuery(script *Script) *ScriptQuery {\n\treturn &ScriptQuery{\n\t\tscript: script,\n\t}\n}\n\n// QueryName sets the query name for the filter that can be used\n// when searching for matched_filters per hit\nfunc (q *ScriptQuery) QueryName(queryName string) *ScriptQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the query.\nfunc (q *ScriptQuery) Source() (interface{}, error) {\n\tif q.script == nil {\n\t\treturn nil, errors.New(\"ScriptQuery expected a script\")\n\t}\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"script\"] = params\n\n\tsrc, err := q.script.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tparams[\"script\"] = src\n\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_script_score.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"errors\"\n\n// ScriptScoreQuery uses a script to provide a custom score for returned documents.\n//\n// A ScriptScoreQuery query is useful if, for example, a scoring function is\n// expensive and you only need to calculate the score of a filtered set of documents.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl-script-score-query.html\ntype ScriptScoreQuery struct {\n\tquery     Query\n\tscript    *Script\n\tminScore  *float64\n\tboost     *float64\n\tqueryName string\n}\n\n// NewScriptScoreQuery creates and initializes a new script_score query.\nfunc NewScriptScoreQuery(query Query, script *Script) *ScriptScoreQuery {\n\treturn &ScriptScoreQuery{\n\t\tquery: query,\n\t\tscript: script,\n\t}\n}\n\n// Query to be used in the ScriptScoreQuery.\nfunc (q *ScriptScoreQuery) Query(query Query) *ScriptScoreQuery {\n\tq.query = query\n\treturn q\n}\n\n// Script to calculate the score.\nfunc (q *ScriptScoreQuery) Script(script *Script) *ScriptScoreQuery {\n\tq.script = script\n\treturn q\n}\n\n// MinScore sets the minimum score.\nfunc (q *ScriptScoreQuery) MinScore(minScore float64) *ScriptScoreQuery {\n\tq.minScore = &minScore\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *ScriptScoreQuery) Boost(boost float64) *ScriptScoreQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter.\nfunc (q *ScriptScoreQuery) QueryName(queryName string) *ScriptScoreQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the function score query.\nfunc (q *ScriptScoreQuery) Source() (interface{}, error) {\n\t// {\n\t//   \"script_score\" : {\n\t//     \"query\" : {\n\t//       \"match\" : { \"message\": \"elasticsearch\" }\n\t//     },\n\t//     \"script\" : {\n\t//       \"source\" : \"doc['likes'].value / 10\"\n\t//     }\n\t//\t }\n\t// }\n\n\tsource := make(map[string]interface{})\n\tquery := make(map[string]interface{})\n\tsource[\"script_score\"] = query\n\n\tif q.query == nil {\n\t\treturn nil, errors.New(\"ScriptScoreQuery: Query is missing\")\n\t}\n\tif q.script == nil {\n\t\treturn nil, errors.New(\"ScriptScoreQuery: Script is missing\")\n\t}\n\n\tif src, err := q.query.Source(); err != nil {\n\t\treturn nil, err\n\t} else {\n\t\tquery[\"query\"] = src\n\t}\n\n\tif src, err := q.script.Source(); err != nil {\n\t\treturn nil, err\n\t} else {\n\t\tquery[\"script\"] = src\n\t}\n\n\tif v := q.minScore; v != nil {\n\t\tquery[\"min_score\"] = *v\n\t}\n\n\tif v := q.boost; v != nil {\n\t\tquery[\"boost\"] = *v\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_script_score_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestScriptScoreQuery(t *testing.T) {\n\tq := NewScriptScoreQuery(\n\t\tNewMatchQuery(\"message\", \"elasticsearch\"),\n\t\tNewScript(\"doc['likes'].value / 10\"),\n\t).MinScore(1.1).Boost(5.0).QueryName(\"my_query\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"script_score\":{\"_name\":\"my_query\",\"boost\":5,\"min_score\":1.1,\"query\":{\"match\":{\"message\":{\"query\":\"elasticsearch\"}}},\"script\":{\"source\":\"doc['likes'].value / 10\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScriptScoreQueryIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tres, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(\n\t\t\tNewScriptScoreQuery(\n\t\t\t\tNewMatchQuery(\"message\", \"Golang\"),\n\t\t\t\tNewScript(\"(1 + doc['retweets'].value) * 10\"),\n\t\t\t),\n\t\t).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected Hits != nil; got nil\")\n\t}\n\tif want, have := int64(1), res.TotalHits(); want != have {\n\t\tt.Errorf(\"expected TotalHits() = %d; got %d\", want, have)\n\t}\n\tif want, have := 1, len(res.Hits.Hits); want != have {\n\t\tt.Errorf(\"expected len(Hits.Hits) = %d; got %d\", want, have)\n\t}\n\n\thit := res.Hits.Hits[0]\n\n\tif want, have := testIndexName, hit.Index; want != have {\n\t\tt.Fatalf(\"expected Hits.Hit.Index = %q; got %q\", want, have)\n\t}\n\tif want, have := \"1\", hit.Id; want != have {\n\t\tt.Fatalf(\"expected Hits.Hit.Id = %q; got %q\", want, have)\n\t}\n\tif hit.Score == nil {\n\t\tt.Fatal(\"expected Hits.Hit.Score != nil\")\n\t}\n\tif want, have := float64(1090), *hit.Score; want != have {\n\t\tt.Fatalf(\"expected Hits.Hit.Score = %v; got %v\", want, have)\n\t}\n\tvar tw tweet\n\tif err := json.Unmarshal(hit.Source, &tw); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := \"olivere\", tw.User; want != have {\n\t\tt.Fatalf(\"expected User = %q; got %q\", want, have)\n\t}\n}\n"
  },
  {
    "path": "search_queries_script_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestScriptQuery(t *testing.T) {\n\tq := NewScriptQuery(NewScript(\"doc['num1'.value > 1\"))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"script\":{\"script\":{\"source\":\"doc['num1'.value \\u003e 1\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScriptQueryWithParams(t *testing.T) {\n\tq := NewScriptQuery(NewScript(\"doc['num1'.value > 1\"))\n\tq = q.QueryName(\"MyQueryName\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"script\":{\"_name\":\"MyQueryName\",\"script\":{\"source\":\"doc['num1'.value \\u003e 1\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_simple_query_string.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\n// SimpleQueryStringQuery is a query that uses the SimpleQueryParser\n// to parse its context. Unlike the regular query_string query,\n// the simple_query_string query will never throw an exception,\n// and discards invalid parts of the query.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-simple-query-string-query.html\ntype SimpleQueryStringQuery struct {\n\tqueryText                       string\n\tanalyzer                        string\n\tquoteFieldSuffix                string\n\tdefaultOperator                 string\n\tfields                          []string\n\tfieldBoosts                     map[string]*float64\n\tminimumShouldMatch              string\n\tflags                           string\n\tboost                           *float64\n\tlowercaseExpandedTerms          *bool // deprecated\n\tlenient                         *bool\n\tanalyzeWildcard                 *bool\n\tlocale                          string // deprecated\n\tqueryName                       string\n\tautoGenerateSynonymsPhraseQuery *bool\n\tfuzzyPrefixLength               int\n\tfuzzyMaxExpansions              int\n\tfuzzyTranspositions             *bool\n}\n\n// NewSimpleQueryStringQuery creates and initializes a new SimpleQueryStringQuery.\nfunc NewSimpleQueryStringQuery(text string) *SimpleQueryStringQuery {\n\treturn &SimpleQueryStringQuery{\n\t\tqueryText:          text,\n\t\tfields:             make([]string, 0),\n\t\tfieldBoosts:        make(map[string]*float64),\n\t\tfuzzyPrefixLength:  -1,\n\t\tfuzzyMaxExpansions: -1,\n\t}\n}\n\n// Field adds a field to run the query against.\nfunc (q *SimpleQueryStringQuery) Field(field string) *SimpleQueryStringQuery {\n\tq.fields = append(q.fields, field)\n\treturn q\n}\n\n// Field adds a field to run the query against with a specific boost.\nfunc (q *SimpleQueryStringQuery) FieldWithBoost(field string, boost float64) *SimpleQueryStringQuery {\n\tq.fields = append(q.fields, field)\n\tq.fieldBoosts[field] = &boost\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *SimpleQueryStringQuery) Boost(boost float64) *SimpleQueryStringQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QuoteFieldSuffix is an optional field name suffix to automatically\n// try and add to the field searched when using quoted text.\nfunc (q *SimpleQueryStringQuery) QuoteFieldSuffix(quoteFieldSuffix string) *SimpleQueryStringQuery {\n\tq.quoteFieldSuffix = quoteFieldSuffix\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched_filters per hit.\nfunc (q *SimpleQueryStringQuery) QueryName(queryName string) *SimpleQueryStringQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Analyzer specifies the analyzer to use for the query.\nfunc (q *SimpleQueryStringQuery) Analyzer(analyzer string) *SimpleQueryStringQuery {\n\tq.analyzer = analyzer\n\treturn q\n}\n\n// DefaultOperator specifies the default operator for the query.\nfunc (q *SimpleQueryStringQuery) DefaultOperator(defaultOperator string) *SimpleQueryStringQuery {\n\tq.defaultOperator = defaultOperator\n\treturn q\n}\n\n// Flags sets the flags for the query.\nfunc (q *SimpleQueryStringQuery) Flags(flags string) *SimpleQueryStringQuery {\n\tq.flags = flags\n\treturn q\n}\n\n// LowercaseExpandedTerms indicates whether terms of wildcard, prefix, fuzzy\n// and range queries are automatically lower-cased or not. Default is true.\n//\n// Deprecated: Decision is now made by the analyzer.\nfunc (q *SimpleQueryStringQuery) LowercaseExpandedTerms(lowercaseExpandedTerms bool) *SimpleQueryStringQuery {\n\tq.lowercaseExpandedTerms = &lowercaseExpandedTerms\n\treturn q\n}\n\n// Locale to be used in the query.\n//\n// Deprecated: Decision is now made by the analyzer.\nfunc (q *SimpleQueryStringQuery) Locale(locale string) *SimpleQueryStringQuery {\n\tq.locale = locale\n\treturn q\n}\n\n// Lenient indicates whether the query string parser should be lenient\n// when parsing field values. It defaults to the index setting and if not\n// set, defaults to false.\nfunc (q *SimpleQueryStringQuery) Lenient(lenient bool) *SimpleQueryStringQuery {\n\tq.lenient = &lenient\n\treturn q\n}\n\n// AnalyzeWildcard indicates whether to enabled analysis on wildcard and prefix queries.\nfunc (q *SimpleQueryStringQuery) AnalyzeWildcard(analyzeWildcard bool) *SimpleQueryStringQuery {\n\tq.analyzeWildcard = &analyzeWildcard\n\treturn q\n}\n\n// MinimumShouldMatch specifies the minimumShouldMatch to apply to the\n// resulting query should that be a Boolean query.\nfunc (q *SimpleQueryStringQuery) MinimumShouldMatch(minimumShouldMatch string) *SimpleQueryStringQuery {\n\tq.minimumShouldMatch = minimumShouldMatch\n\treturn q\n}\n\n// AutoGenerateSynonymsPhraseQuery indicates whether phrase queries should be\n// automatically generated for multi terms synonyms. Defaults to true.\nfunc (q *SimpleQueryStringQuery) AutoGenerateSynonymsPhraseQuery(enable bool) *SimpleQueryStringQuery {\n\tq.autoGenerateSynonymsPhraseQuery = &enable\n\treturn q\n}\n\n// FuzzyPrefixLength defines the prefix length in fuzzy queries.\nfunc (q *SimpleQueryStringQuery) FuzzyPrefixLength(fuzzyPrefixLength int) *SimpleQueryStringQuery {\n\tq.fuzzyPrefixLength = fuzzyPrefixLength\n\treturn q\n}\n\n// FuzzyMaxExpansions defines the number of terms fuzzy queries will expand to.\nfunc (q *SimpleQueryStringQuery) FuzzyMaxExpansions(fuzzyMaxExpansions int) *SimpleQueryStringQuery {\n\tq.fuzzyMaxExpansions = fuzzyMaxExpansions\n\treturn q\n}\n\n// FuzzyTranspositions defines whether to use transpositions in fuzzy queries.\nfunc (q *SimpleQueryStringQuery) FuzzyTranspositions(fuzzyTranspositions bool) *SimpleQueryStringQuery {\n\tq.fuzzyTranspositions = &fuzzyTranspositions\n\treturn q\n}\n\n// Source returns JSON for the query.\nfunc (q *SimpleQueryStringQuery) Source() (interface{}, error) {\n\t// {\n\t//    \"simple_query_string\" : {\n\t//      \"query\" : \"\\\"fried eggs\\\" +(eggplant | potato) -frittata\",\n\t//\t\t\t\"analyzer\" : \"snowball\",\n\t//      \"fields\" : [\"body^5\",\"_all\"],\n\t//      \"default_operator\" : \"and\"\n\t//    }\n\t// }\n\n\tsource := make(map[string]interface{})\n\n\tquery := make(map[string]interface{})\n\tsource[\"simple_query_string\"] = query\n\n\tquery[\"query\"] = q.queryText\n\n\tif len(q.fields) > 0 {\n\t\tvar fields []string\n\t\tfor _, field := range q.fields {\n\t\t\tif boost, found := q.fieldBoosts[field]; found {\n\t\t\t\tif boost != nil {\n\t\t\t\t\tfields = append(fields, fmt.Sprintf(\"%s^%f\", field, *boost))\n\t\t\t\t} else {\n\t\t\t\t\tfields = append(fields, field)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfields = append(fields, field)\n\t\t\t}\n\t\t}\n\t\tquery[\"fields\"] = fields\n\t}\n\n\tif q.flags != \"\" {\n\t\tquery[\"flags\"] = q.flags\n\t}\n\tif q.analyzer != \"\" {\n\t\tquery[\"analyzer\"] = q.analyzer\n\t}\n\tif q.defaultOperator != \"\" {\n\t\tquery[\"default_operator\"] = strings.ToLower(q.defaultOperator)\n\t}\n\tif q.lowercaseExpandedTerms != nil {\n\t\tquery[\"lowercase_expanded_terms\"] = *q.lowercaseExpandedTerms\n\t}\n\tif q.lenient != nil {\n\t\tquery[\"lenient\"] = *q.lenient\n\t}\n\tif q.analyzeWildcard != nil {\n\t\tquery[\"analyze_wildcard\"] = *q.analyzeWildcard\n\t}\n\tif q.locale != \"\" {\n\t\tquery[\"locale\"] = q.locale\n\t}\n\tif q.queryName != \"\" {\n\t\tquery[\"_name\"] = q.queryName\n\t}\n\tif q.minimumShouldMatch != \"\" {\n\t\tquery[\"minimum_should_match\"] = q.minimumShouldMatch\n\t}\n\tif q.quoteFieldSuffix != \"\" {\n\t\tquery[\"quote_field_suffix\"] = q.quoteFieldSuffix\n\t}\n\tif q.boost != nil {\n\t\tquery[\"boost\"] = *q.boost\n\t}\n\tif v := q.autoGenerateSynonymsPhraseQuery; v != nil {\n\t\tquery[\"auto_generate_synonyms_phrase_query\"] = *v\n\t}\n\tif v := q.fuzzyPrefixLength; v != -1 {\n\t\tquery[\"fuzzy_prefix_length\"] = v\n\t}\n\tif v := q.fuzzyMaxExpansions; v != -1 {\n\t\tquery[\"fuzzy_max_expansions\"] = v\n\t}\n\tif v := q.fuzzyTranspositions; v != nil {\n\t\tquery[\"fuzzy_transpositions\"] = *v\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_simple_query_string_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSimpleQueryStringQuery(t *testing.T) {\n\tq := NewSimpleQueryStringQuery(`\"fried eggs\" +(eggplant | potato) -frittata`)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"simple_query_string\":{\"query\":\"\\\"fried eggs\\\" +(eggplant | potato) -frittata\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSimpleQueryStringQueryExec(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewSimpleQueryStringQuery(\"+Golang +Elasticsearch\")).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 1 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 1, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 1 {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 1, len(searchResult.Hits.Hits))\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "search_queries_slice.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SliceQuery allows to partition the documents into several slices.\n// It is used e.g. to slice scroll operations in Elasticsearch 5.0 or later.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-scroll.html#sliced-scroll\n// for details.\ntype SliceQuery struct {\n\tfield string\n\tid    *int\n\tmax   *int\n}\n\n// NewSliceQuery creates a new SliceQuery.\nfunc NewSliceQuery() *SliceQuery {\n\treturn &SliceQuery{}\n}\n\n// Field is the name of the field to slice against (_uid by default).\nfunc (s *SliceQuery) Field(field string) *SliceQuery {\n\ts.field = field\n\treturn s\n}\n\n// Id is the id of the slice.\nfunc (s *SliceQuery) Id(id int) *SliceQuery {\n\ts.id = &id\n\treturn s\n}\n\n// Max is the maximum number of slices.\nfunc (s *SliceQuery) Max(max int) *SliceQuery {\n\ts.max = &max\n\treturn s\n}\n\n// Source returns the JSON body.\nfunc (s *SliceQuery) Source() (interface{}, error) {\n\tm := make(map[string]interface{})\n\tif s.field != \"\" {\n\t\tm[\"field\"] = s.field\n\t}\n\tif s.id != nil {\n\t\tm[\"id\"] = *s.id\n\t}\n\tif s.max != nil {\n\t\tm[\"max\"] = *s.max\n\t}\n\treturn m, nil\n}\n"
  },
  {
    "path": "search_queries_slice_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSliceQuery(t *testing.T) {\n\tq := NewSliceQuery().Field(\"date\").Id(0).Max(2)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"field\":\"date\",\"id\":0,\"max\":2}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_span_first.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SpanFirstQuery spans near the beginning of a field.\n// The span first query maps to Lucene SpanFirstQuery\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.7/query-dsl-span-first-query.html\n// for details.\ntype SpanFirstQuery struct {\n\tmatch     Query\n\tend       int\n\tboost     *float64\n\tqueryName string\n}\n\n// NewSpanFirstQuery creates a new SpanFirstQuery.\nfunc NewSpanFirstQuery(query Query, end int) *SpanFirstQuery {\n\treturn &SpanFirstQuery{\n\t\tmatch: query,\n\t\tend:   end,\n\t}\n}\n\n// Match sets the query, e.g. a SpanTermQuery.\nfunc (q *SpanFirstQuery) Match(query Query) *SpanFirstQuery {\n\tq.match = query\n\treturn q\n}\n\n// End specifies the maximum end position of the match, which needs to be positive.\nfunc (q *SpanFirstQuery) End(end int) *SpanFirstQuery {\n\tq.end = end\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *SpanFirstQuery) Boost(boost float64) *SpanFirstQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched_filters per hit.\nfunc (q *SpanFirstQuery) QueryName(queryName string) *SpanFirstQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns the JSON body.\nfunc (q *SpanFirstQuery) Source() (interface{}, error) {\n\tm := make(map[string]interface{})\n\tc := make(map[string]interface{})\n\n\tif v := q.match; v != nil {\n\t\tsrc, err := q.match.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tc[\"match\"] = src\n\t}\n\tc[\"end\"] = q.end\n\n\tif v := q.boost; v != nil {\n\t\tc[\"boost\"] = *v\n\t}\n\tif v := q.queryName; v != \"\" {\n\t\tc[\"query_name\"] = v\n\t}\n\tm[\"span_first\"] = c\n\treturn m, nil\n}\n"
  },
  {
    "path": "search_queries_span_first_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestSpanFirstQueryIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\t_, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewSpanFirstQuery(NewSpanTermQuery(\"message\", \"Golang\"), 1)).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "search_queries_span_first_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSpanFirstQuery(t *testing.T) {\n\tq := NewSpanFirstQuery(\n\t\tNewSpanTermQuery(\"user\", \"kimchy\"),\n\t\t3,\n\t)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"span_first\":{\"end\":3,\"match\":{\"span_term\":{\"user\":{\"value\":\"kimchy\"}}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_span_near.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SpanNearQuery matches spans which are near one another. One can specify slop,\n// the maximum number of intervening unmatched positions, as well as whether\n// matches are required to be in-order. The span near query maps to Lucene SpanNearQuery.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.7/query-dsl-span-near-query.html\n// for details.\ntype SpanNearQuery struct {\n\tclauses   []Query\n\tslop      *int\n\tinOrder   *bool\n\tboost     *float64\n\tqueryName string\n}\n\n// NewSpanNearQuery creates a new SpanNearQuery.\nfunc NewSpanNearQuery(clauses ...Query) *SpanNearQuery {\n\treturn &SpanNearQuery{\n\t\tclauses: clauses,\n\t}\n}\n\n// Add clauses to use in the query.\nfunc (q *SpanNearQuery) Add(clauses ...Query) *SpanNearQuery {\n\tq.clauses = append(q.clauses, clauses...)\n\treturn q\n}\n\n// Clauses to use in the query.\nfunc (q *SpanNearQuery) Clauses(clauses ...Query) *SpanNearQuery {\n\tq.clauses = clauses\n\treturn q\n}\n\n// Slop controls the maximum number of intervening unmatched positions permitted.\nfunc (q *SpanNearQuery) Slop(slop int) *SpanNearQuery {\n\tq.slop = &slop\n\treturn q\n}\n\n// InOrder, when true, the spans from each clause must be in the same order as\n// in Clauses and must be non-overlapping. Defaults to true.\nfunc (q *SpanNearQuery) InOrder(inOrder bool) *SpanNearQuery {\n\tq.inOrder = &inOrder\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *SpanNearQuery) Boost(boost float64) *SpanNearQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched_filters per hit.\nfunc (q *SpanNearQuery) QueryName(queryName string) *SpanNearQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns the JSON body.\nfunc (q *SpanNearQuery) Source() (interface{}, error) {\n\tm := make(map[string]interface{})\n\tc := make(map[string]interface{})\n\n\tif len(q.clauses) > 0 {\n\t\tvar clauses []interface{}\n\t\tfor _, clause := range q.clauses {\n\t\t\tsrc, err := clause.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tclauses = append(clauses, src)\n\t\t}\n\t\tc[\"clauses\"] = clauses\n\t}\n\n\tif v := q.slop; v != nil {\n\t\tc[\"slop\"] = *v\n\t}\n\tif v := q.inOrder; v != nil {\n\t\tc[\"in_order\"] = *v\n\t}\n\n\tif v := q.boost; v != nil {\n\t\tc[\"boost\"] = *v\n\t}\n\tif v := q.queryName; v != \"\" {\n\t\tc[\"query_name\"] = v\n\t}\n\tm[\"span_near\"] = c\n\treturn m, nil\n}\n"
  },
  {
    "path": "search_queries_span_near_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestSpanNearQueryIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\t_, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(\n\t\t\tNewSpanNearQuery(\n\t\t\t\tNewSpanTermQuery(\"message\", \"Golang\"),\n\t\t\t\tNewSpanTermQuery(\"message\", \"Elasticsearch\"),\n\t\t\t).Boost(2),\n\t\t).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "search_queries_span_near_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSpanNearQuery(t *testing.T) {\n\tq := NewSpanNearQuery(\n\t\tNewSpanTermQuery(\"field\", \"value1\"),\n\t\tNewSpanTermQuery(\"field\", \"value2\"),\n\t\tNewSpanTermQuery(\"field\", \"value3\"),\n\t).Slop(12).InOrder(false)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"span_near\":{\"clauses\":[{\"span_term\":{\"field\":{\"value\":\"value1\"}}},{\"span_term\":{\"field\":{\"value\":\"value2\"}}},{\"span_term\":{\"field\":{\"value\":\"value3\"}}}],\"in_order\":false,\"slop\":12}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_span_term.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// SpanTermQuery matches spans containing a term. The span term query maps to Lucene SpanTermQuery.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.7/query-dsl-span-term-query.html\n// for details.\ntype SpanTermQuery struct {\n\tfield     string\n\tvalue     interface{}\n\tboost     *float64\n\tqueryName string\n}\n\n// NewSpanTermQuery creates a new SpanTermQuery. When passing values, the first one\n// is used to initialize the value.\nfunc NewSpanTermQuery(field string, value ...interface{}) *SpanTermQuery {\n\tq := &SpanTermQuery{\n\t\tfield: field,\n\t}\n\tif len(value) > 0 {\n\t\tq.value = value[0]\n\t}\n\treturn q\n}\n\n// Field name to match the term against.\nfunc (q *SpanTermQuery) Field(field string) *SpanTermQuery {\n\tq.field = field\n\treturn q\n}\n\n// Value of the term.\nfunc (q *SpanTermQuery) Value(value interface{}) *SpanTermQuery {\n\tq.value = value\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *SpanTermQuery) Boost(boost float64) *SpanTermQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used when\n// searching for matched_filters per hit.\nfunc (q *SpanTermQuery) QueryName(queryName string) *SpanTermQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns the JSON body.\nfunc (q *SpanTermQuery) Source() (interface{}, error) {\n\tm := make(map[string]interface{})\n\tc := make(map[string]interface{})\n\ti := make(map[string]interface{})\n\ti[\"value\"] = q.value\n\tif v := q.boost; v != nil {\n\t\ti[\"boost\"] = *v\n\t}\n\tif v := q.queryName; v != \"\" {\n\t\ti[\"query_name\"] = v\n\t}\n\tc[q.field] = i\n\tm[\"span_term\"] = c\n\treturn m, nil\n}\n"
  },
  {
    "path": "search_queries_span_term_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestSpanTermQueryIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\t_, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewSpanTermQuery(\"message\", \"Golang\")).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "search_queries_span_term_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSpanTermQuery(t *testing.T) {\n\tq := NewSpanTermQuery(\"user\", \"kimchy\").Boost(2.5)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"span_term\":{\"user\":{\"boost\":2.5,\"value\":\"kimchy\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSpanTermQueryWithFieldAndValue(t *testing.T) {\n\tq := NewSpanTermQuery(\"user\").Value(\"kimchy\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"span_term\":{\"user\":{\"value\":\"kimchy\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_term.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// TermQuery finds documents that contain the exact term specified\n// in the inverted index.\n//\n// For details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-term-query.html\ntype TermQuery struct {\n\tname            string\n\tvalue           interface{}\n\tboost           *float64\n\tcaseInsensitive *bool\n\tqueryName       string\n}\n\n// NewTermQuery creates and initializes a new TermQuery.\nfunc NewTermQuery(name string, value interface{}) *TermQuery {\n\treturn &TermQuery{name: name, value: value}\n}\n\n// Boost sets the boost for this query.\nfunc (q *TermQuery) Boost(boost float64) *TermQuery {\n\tq.boost = &boost\n\treturn q\n}\n\nfunc (q *TermQuery) CaseInsensitive(caseInsensitive bool) *TermQuery {\n\tq.caseInsensitive = &caseInsensitive\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used\n// when searching for matched_filters per hit\nfunc (q *TermQuery) QueryName(queryName string) *TermQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source returns JSON for the query.\nfunc (q *TermQuery) Source() (interface{}, error) {\n\t// {\"term\":{\"name\":\"value\"}}\n\tsource := make(map[string]interface{})\n\ttq := make(map[string]interface{})\n\tsource[\"term\"] = tq\n\n\tif q.boost == nil && q.caseInsensitive == nil && q.queryName == \"\" {\n\t\ttq[q.name] = q.value\n\t} else {\n\t\tsubQ := make(map[string]interface{})\n\t\tsubQ[\"value\"] = q.value\n\t\tif q.boost != nil {\n\t\t\tsubQ[\"boost\"] = *q.boost\n\t\t}\n\t\tif q.caseInsensitive != nil {\n\t\t\tsubQ[\"case_insensitive\"] = *q.caseInsensitive\n\t\t}\n\t\tif q.queryName != \"\" {\n\t\t\tsubQ[\"_name\"] = q.queryName\n\t\t}\n\t\ttq[q.name] = subQ\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_term_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestTermQuery(t *testing.T) {\n\tq := NewTermQuery(\"user\", \"ki\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"term\":{\"user\":\"ki\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermQueryWithCaseInsensitive(t *testing.T) {\n\tq := NewTermQuery(\"user\", \"ki\").CaseInsensitive(true)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"term\":{\"user\":{\"case_insensitive\":true,\"value\":\"ki\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermQueryWithOptions(t *testing.T) {\n\tq := NewTermQuery(\"user\", \"ki\")\n\tq = q.Boost(2.79)\n\tq = q.QueryName(\"my_tq\")\n\tq = q.CaseInsensitive(true)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"term\":{\"user\":{\"_name\":\"my_tq\",\"boost\":2.79,\"case_insensitive\":true,\"value\":\"ki\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_terms.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// TermsQuery filters documents that have fields that match any\n// of the provided terms (not analyzed).\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-terms-query.html\ntype TermsQuery struct {\n\tname        string\n\tvalues      []interface{}\n\ttermsLookup *TermsLookup\n\tqueryName   string\n\tboost       *float64\n}\n\n// NewTermsQuery creates and initializes a new TermsQuery.\nfunc NewTermsQuery(name string, values ...interface{}) *TermsQuery {\n\tq := &TermsQuery{\n\t\tname:   name,\n\t\tvalues: make([]interface{}, 0),\n\t}\n\tif len(values) > 0 {\n\t\tq.values = append(q.values, values...)\n\t}\n\treturn q\n}\n\n// NewTermsQueryFromStrings creates and initializes a new TermsQuery\n// from strings.\nfunc NewTermsQueryFromStrings(name string, values ...string) *TermsQuery {\n\tq := &TermsQuery{\n\t\tname:   name,\n\t\tvalues: make([]interface{}, 0),\n\t}\n\tfor _, v := range values {\n\t\tq.values = append(q.values, v)\n\t}\n\treturn q\n}\n\n// TermsLookup adds terms lookup details to the query.\nfunc (q *TermsQuery) TermsLookup(lookup *TermsLookup) *TermsQuery {\n\tq.termsLookup = lookup\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *TermsQuery) Boost(boost float64) *TermsQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used\n// when searching for matched_filters per hit\nfunc (q *TermsQuery) QueryName(queryName string) *TermsQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Creates the query source for the term query.\nfunc (q *TermsQuery) Source() (interface{}, error) {\n\t// {\"terms\":{\"name\":[\"value1\",\"value2\"]}}\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"terms\"] = params\n\n\tif q.termsLookup != nil {\n\t\tsrc, err := q.termsLookup.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tparams[q.name] = src\n\t} else {\n\t\tparams[q.name] = q.values\n\t\tif q.boost != nil {\n\t\t\tparams[\"boost\"] = *q.boost\n\t\t}\n\t\tif q.queryName != \"\" {\n\t\t\tparams[\"_name\"] = q.queryName\n\t\t}\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_terms_set.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// TermsSetQuery returns any documents that match with at least\n// one or more of the provided terms. The terms are not analyzed\n// and thus must match exactly. The number of terms that must\n// match varies per document and is either controlled by a\n// minimum should match field or computed per document in a\n// minimum should match script.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-terms-set-query.html\ntype TermsSetQuery struct {\n\tname                     string\n\tvalues                   []interface{}\n\tminimumShouldMatchField  string\n\tminimumShouldMatchScript *Script\n\tqueryName                string\n\tboost                    *float64\n}\n\n// NewTermsSetQuery creates and initializes a new TermsSetQuery.\nfunc NewTermsSetQuery(name string, values ...interface{}) *TermsSetQuery {\n\tq := &TermsSetQuery{\n\t\tname:   name,\n\t\tvalues: make([]interface{}, 0),\n\t}\n\tif len(values) > 0 {\n\t\tq.values = append(q.values, values...)\n\t}\n\treturn q\n}\n\n// MinimumShouldMatchField specifies the field to match.\nfunc (q *TermsSetQuery) MinimumShouldMatchField(minimumShouldMatchField string) *TermsSetQuery {\n\tq.minimumShouldMatchField = minimumShouldMatchField\n\treturn q\n}\n\n// MinimumShouldMatchScript specifies the script to match.\nfunc (q *TermsSetQuery) MinimumShouldMatchScript(minimumShouldMatchScript *Script) *TermsSetQuery {\n\tq.minimumShouldMatchScript = minimumShouldMatchScript\n\treturn q\n}\n\n// Boost sets the boost for this query.\nfunc (q *TermsSetQuery) Boost(boost float64) *TermsSetQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// QueryName sets the query name for the filter that can be used\n// when searching for matched_filters per hit\nfunc (q *TermsSetQuery) QueryName(queryName string) *TermsSetQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// Source creates the query source for the term query.\nfunc (q *TermsSetQuery) Source() (interface{}, error) {\n\t// {\"terms_set\":{\"codes\":{\"terms\":[\"abc\",\"def\"],\"minimum_should_match_field\":\"required_matches\"}}}\n\tsource := make(map[string]interface{})\n\tinner := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tinner[q.name] = params\n\tsource[\"terms_set\"] = inner\n\n\t// terms\n\tparams[\"terms\"] = q.values\n\n\t// minimum_should_match_field\n\tif match := q.minimumShouldMatchField; match != \"\" {\n\t\tparams[\"minimum_should_match_field\"] = match\n\t}\n\n\t// minimum_should_match_script\n\tif match := q.minimumShouldMatchScript; match != nil {\n\t\tsrc, err := match.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tparams[\"minimum_should_match_script\"] = src\n\t}\n\n\t// Common parameters for all queries\n\tif q.boost != nil {\n\t\tparams[\"boost\"] = *q.boost\n\t}\n\tif q.queryName != \"\" {\n\t\tparams[\"_name\"] = q.queryName\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_terms_set_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestTermsSetQueryWithField(t *testing.T) {\n\tq := NewTermsSetQuery(\"codes\", \"abc\", \"def\", \"ghi\").MinimumShouldMatchField(\"required_matches\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms_set\":{\"codes\":{\"minimum_should_match_field\":\"required_matches\",\"terms\":[\"abc\",\"def\",\"ghi\"]}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsSetQueryWithScript(t *testing.T) {\n\tq := NewTermsSetQuery(\"codes\", \"abc\", \"def\", \"ghi\").\n\t\tMinimumShouldMatchScript(\n\t\t\tNewScript(`Math.min(params.num_terms, doc['required_matches'].value)`),\n\t\t)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms_set\":{\"codes\":{\"minimum_should_match_script\":{\"source\":\"Math.min(params.num_terms, doc['required_matches'].value)\"},\"terms\":[\"abc\",\"def\",\"ghi\"]}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchTermsSetQuery(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(\n\t\t\tNewTermsSetQuery(\"user\", \"olivere\", \"sandrae\").\n\t\t\t\tMinimumShouldMatchField(\"retweets\"),\n\t\t).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(1); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 1; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_terms_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestTermsQuery(t *testing.T) {\n\tq := NewTermsQuery(\"user\", \"ki\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"user\":[\"ki\"]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsQueryFromStrings(t *testing.T) {\n\tvalues := []string{\"one\", \"two\", \"three\"}\n\tq := NewTermsQueryFromStrings(\"tags\", values...)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"tags\":[\"one\",\"two\",\"three\"]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsQueryWithEmptyArray(t *testing.T) {\n\tincluded := make([]interface{}, 0)\n\tq := NewTermsQuery(\"tags\", included...)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"tags\":[]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermsQueryWithTermsLookup(t *testing.T) {\n\tq := NewTermsQuery(\"user\").\n\t\tTermsLookup(NewTermsLookup().Index(\"users\").Type(\"user\").Id(\"2\").Path(\"followers\"))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"user\":{\"id\":\"2\",\"index\":\"users\",\"path\":\"followers\",\"type\":\"user\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermQuerysWithOptions(t *testing.T) {\n\tq := NewTermsQuery(\"user\", \"ki\", \"ko\")\n\tq = q.Boost(2.79)\n\tq = q.QueryName(\"my_tq\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"terms\":{\"_name\":\"my_tq\",\"boost\":2.79,\"user\":[\"ki\",\"ko\"]}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_type.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// TypeQuery filters documents matching the provided document / mapping type.\n//\n// For details, see:\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-type-query.html\ntype TypeQuery struct {\n\ttyp string\n}\n\nfunc NewTypeQuery(typ string) *TypeQuery {\n\treturn &TypeQuery{typ: typ}\n}\n\n// Source returns JSON for the query.\nfunc (q *TypeQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tparams := make(map[string]interface{})\n\tsource[\"type\"] = params\n\tparams[\"value\"] = q.typ\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_type_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestTypeQuery(t *testing.T) {\n\tq := NewTypeQuery(\"my_type\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"type\":{\"value\":\"my_type\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_wildcard.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// WildcardQuery matches documents that have fields matching a wildcard\n// expression (not analyzed). Supported wildcards are *, which matches\n// any character sequence (including the empty one), and ?, which matches\n// any single character. Note this query can be slow, as it needs to iterate\n// over many terms. In order to prevent extremely slow wildcard queries,\n// a wildcard term should not start with one of the wildcards * or ?.\n// The wildcard query maps to Lucene WildcardQuery.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.x/query-dsl-wildcard-query.html\ntype WildcardQuery struct {\n\tname            string\n\twildcard        string\n\tboost           *float64\n\trewrite         string\n\tqueryName       string\n\tcaseInsensitive *bool\n}\n\n// NewWildcardQuery creates and initializes a new WildcardQuery.\nfunc NewWildcardQuery(name, wildcard string) *WildcardQuery {\n\treturn &WildcardQuery{\n\t\tname:     name,\n\t\twildcard: wildcard,\n\t}\n}\n\n// Boost sets the boost for this query.\nfunc (q *WildcardQuery) Boost(boost float64) *WildcardQuery {\n\tq.boost = &boost\n\treturn q\n}\n\nfunc (q *WildcardQuery) Rewrite(rewrite string) *WildcardQuery {\n\tq.rewrite = rewrite\n\treturn q\n}\n\n// QueryName sets the name of this query.\nfunc (q *WildcardQuery) QueryName(queryName string) *WildcardQuery {\n\tq.queryName = queryName\n\treturn q\n}\n\n// CaseInsensitive sets case insensitive matching of this query.\nfunc (q *WildcardQuery) CaseInsensitive(caseInsensitive bool) *WildcardQuery {\n\tq.caseInsensitive = &caseInsensitive\n\treturn q\n}\n\n// Source returns the JSON serializable body of this query.\nfunc (q *WildcardQuery) Source() (interface{}, error) {\n\t// {\n\t//\t\"wildcard\" : {\n\t//\t\t\"user\" : {\n\t//      \"value\" : \"ki*y\",\n\t//      \"boost\" : 1.0,\n\t//      \"case_insensitive\" : true\n\t//    }\n\t// }\n\n\tsource := make(map[string]interface{})\n\n\tquery := make(map[string]interface{})\n\tsource[\"wildcard\"] = query\n\n\twq := make(map[string]interface{})\n\tquery[q.name] = wq\n\n\twq[\"value\"] = q.wildcard\n\n\tif q.boost != nil {\n\t\twq[\"boost\"] = *q.boost\n\t}\n\tif q.rewrite != \"\" {\n\t\twq[\"rewrite\"] = q.rewrite\n\t}\n\tif q.queryName != \"\" {\n\t\twq[\"_name\"] = q.queryName\n\t}\n\tif q.caseInsensitive != nil {\n\t\twq[\"case_insensitive\"] = *q.caseInsensitive\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_wildcard_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic_test\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc ExampleWildcardQuery() {\n\t// Get a client to the local Elasticsearch instance.\n\tclient, err := elastic.NewClient()\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\n\t// Define wildcard query\n\tq := elastic.NewWildcardQuery(\"user\", \"oli*er?\").Boost(1.2)\n\tsearchResult, err := client.Search().\n\t\tIndex(\"twitter\").  // search in index \"twitter\"\n\t\tQuery(q).          // use wildcard query defined above\n\t\tDo(context.TODO()) // execute\n\tif err != nil {\n\t\t// Handle error\n\t\tpanic(err)\n\t}\n\t_ = searchResult\n}\n\nfunc TestWildcardQuery(t *testing.T) {\n\tq := elastic.NewWildcardQuery(\"user\", \"ki*y??\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"wildcard\":{\"user\":{\"value\":\"ki*y??\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestWildcardQueryWithBoost(t *testing.T) {\n\tq := elastic.NewWildcardQuery(\"user\", \"ki*y??\").Boost(1.2)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"wildcard\":{\"user\":{\"boost\":1.2,\"value\":\"ki*y??\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestWildcardQueryWithCaseInsensitive(t *testing.T) {\n\tq := elastic.NewWildcardQuery(\"user\", \"ki*y??\").CaseInsensitive(true)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"wildcard\":{\"user\":{\"case_insensitive\":true,\"value\":\"ki*y??\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_wrapper.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// WrapperQuery accepts any other query as base64 encoded string.\n//\n// For details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-wrapper-query.html.\ntype WrapperQuery struct {\n\tsource string\n}\n\n// NewWrapperQuery creates and initializes a new WrapperQuery.\nfunc NewWrapperQuery(source string) *WrapperQuery {\n\treturn &WrapperQuery{source: source}\n}\n\n// Source returns JSON for the query.\nfunc (q *WrapperQuery) Source() (interface{}, error) {\n\t// {\"wrapper\":{\"query\":\"...\"}}\n\tsource := make(map[string]interface{})\n\ttq := make(map[string]interface{})\n\tsource[\"wrapper\"] = tq\n\ttq[\"query\"] = q.source\n\treturn source, nil\n}\n"
  },
  {
    "path": "search_queries_wrapper_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestWrapperQueryIntegration(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\ttq := NewTermQuery(\"user\", \"olivere\")\n\tsrc, err := tq.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tbase64string := base64.StdEncoding.EncodeToString(data)\n\n\tq := NewWrapperQuery(base64string)\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(q).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(2); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 2; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n}\n"
  },
  {
    "path": "search_queries_wrapper_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestWrapperQuery(t *testing.T) {\n\tq := NewWrapperQuery(\"eyJ0ZXJtIiA6IHsgInVzZXIiIDogIktpbWNoeSIgfX0=\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"wrapper\":{\"query\":\"eyJ0ZXJtIiA6IHsgInVzZXIiIDogIktpbWNoeSIgfX0=\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_request.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n)\n\n// SearchRequest combines a search request and its\n// query details (see SearchSource).\n// It is used in combination with MultiSearch.\ntype SearchRequest struct {\n\tsearchType                 string\n\tindices                    []string\n\ttypes                      []string\n\trouting                    *string\n\tpreference                 *string\n\trequestCache               *bool\n\tallowPartialSearchResults  *bool\n\tignoreUnavailable          *bool\n\tallowNoIndices             *bool\n\texpandWildcards            string\n\tscroll                     string\n\tsource                     interface{}\n\tsearchSource               *SearchSource\n\tbatchedReduceSize          *int\n\tmaxConcurrentShardRequests *int\n\tpreFilterShardSize         *int\n}\n\n// NewSearchRequest creates a new search request.\nfunc NewSearchRequest() *SearchRequest {\n\treturn &SearchRequest{\n\t\tsearchSource: NewSearchSource(),\n\t}\n}\n\n// SearchType must be one of \"dfs_query_then_fetch\", \"dfs_query_and_fetch\",\n// \"query_then_fetch\", or \"query_and_fetch\".\nfunc (r *SearchRequest) SearchType(searchType string) *SearchRequest {\n\tr.searchType = searchType\n\treturn r\n}\n\n// SearchTypeDfsQueryThenFetch sets search type to \"dfs_query_then_fetch\".\nfunc (r *SearchRequest) SearchTypeDfsQueryThenFetch() *SearchRequest {\n\treturn r.SearchType(\"dfs_query_then_fetch\")\n}\n\n// SearchTypeQueryThenFetch sets search type to \"query_then_fetch\".\nfunc (r *SearchRequest) SearchTypeQueryThenFetch() *SearchRequest {\n\treturn r.SearchType(\"query_then_fetch\")\n}\n\n// Index specifies the indices to use in the request.\nfunc (r *SearchRequest) Index(indices ...string) *SearchRequest {\n\tr.indices = append(r.indices, indices...)\n\treturn r\n}\n\n// HasIndices returns true if there are indices used, false otherwise.\nfunc (r *SearchRequest) HasIndices() bool {\n\treturn len(r.indices) > 0\n}\n\n// Type specifies one or more types to be used.\n//\n// Deprecated: Types are in the process of being removed. Instead of using a type, prefer to\n// filter on a field on the document.\nfunc (r *SearchRequest) Type(types ...string) *SearchRequest {\n\tr.types = append(r.types, types...)\n\treturn r\n}\n\n// Routing specifies the routing parameter. It is a comma-separated list.\nfunc (r *SearchRequest) Routing(routing string) *SearchRequest {\n\tr.routing = &routing\n\treturn r\n}\n\n// Routings to be used in the request.\nfunc (r *SearchRequest) Routings(routings ...string) *SearchRequest {\n\tif routings != nil {\n\t\troutings := strings.Join(routings, \",\")\n\t\tr.routing = &routings\n\t} else {\n\t\tr.routing = nil\n\t}\n\treturn r\n}\n\n// Preference to execute the search. Defaults to randomize across shards.\n// Can be set to \"_local\" to prefer local shards, \"_primary\" to execute\n// only on primary shards, or a custom value, which guarantees that the\n// same order will be used across different requests.\nfunc (r *SearchRequest) Preference(preference string) *SearchRequest {\n\tr.preference = &preference\n\treturn r\n}\n\n// RequestCache specifies if this request should use the request cache\n// or not, assuming that it can. By default, will default to the index\n// level setting if request cache is enabled or not.\nfunc (r *SearchRequest) RequestCache(requestCache bool) *SearchRequest {\n\tr.requestCache = &requestCache\n\treturn r\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *SearchRequest) IgnoreUnavailable(ignoreUnavailable bool) *SearchRequest {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified).\nfunc (s *SearchRequest) AllowNoIndices(allowNoIndices bool) *SearchRequest {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *SearchRequest) ExpandWildcards(expandWildcards string) *SearchRequest {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// Scroll, if set, will enable scrolling of the search request.\n// Pass a timeout value, e.g. \"2m\" or \"30s\" as a value.\nfunc (r *SearchRequest) Scroll(scroll string) *SearchRequest {\n\tr.scroll = scroll\n\treturn r\n}\n\n// SearchSource allows passing your own SearchSource, overriding\n// all values set on the request (except Source).\nfunc (r *SearchRequest) SearchSource(searchSource *SearchSource) *SearchRequest {\n\tif searchSource == nil {\n\t\tr.searchSource = NewSearchSource()\n\t\treturn r\n\t}\n\tr.searchSource = searchSource\n\treturn r\n}\n\n// Source allows passing your own request body. It will have preference over\n// all other properties set on the request.\nfunc (r *SearchRequest) Source(source interface{}) *SearchRequest {\n\tr.source = source\n\treturn r\n}\n\n// Timeout value for the request, e.g. \"30s\" or \"2m\".\nfunc (r *SearchRequest) Timeout(timeout string) *SearchRequest {\n\tr.searchSource = r.searchSource.Timeout(timeout)\n\treturn r\n}\n\n// TerminateAfter, when set, specifies an optional document count,\n// upon collecting which the search query will terminate early.\nfunc (r *SearchRequest) TerminateAfter(docs int) *SearchRequest {\n\tr.searchSource = r.searchSource.TerminateAfter(docs)\n\treturn r\n}\n\n// Query for the search.\nfunc (r *SearchRequest) Query(query Query) *SearchRequest {\n\tr.searchSource = r.searchSource.Query(query)\n\treturn r\n}\n\n// PostFilter is a filter that will be executed after the query\n// has been executed and only has affect on the search hits\n// (not aggregations). This filter is always executed as last\n// filtering mechanism.\nfunc (r *SearchRequest) PostFilter(filter Query) *SearchRequest {\n\tr.searchSource = r.searchSource.PostFilter(filter)\n\treturn r\n}\n\n// MinScore below which documents are filtered out.\nfunc (r *SearchRequest) MinScore(minScore float64) *SearchRequest {\n\tr.searchSource = r.searchSource.MinScore(minScore)\n\treturn r\n}\n\n// From index to start search from (default is 0).\nfunc (r *SearchRequest) From(from int) *SearchRequest {\n\tr.searchSource = r.searchSource.From(from)\n\treturn r\n}\n\n// Size is the number of search hits to return (default is 10).\nfunc (r *SearchRequest) Size(size int) *SearchRequest {\n\tr.searchSource = r.searchSource.Size(size)\n\treturn r\n}\n\n// Explain indicates whether to return an explanation for each hit.\nfunc (r *SearchRequest) Explain(explain bool) *SearchRequest {\n\tr.searchSource = r.searchSource.Explain(explain)\n\treturn r\n}\n\n// Version indicates whether each hit should be returned with\n// its version.\nfunc (r *SearchRequest) Version(version bool) *SearchRequest {\n\tr.searchSource = r.searchSource.Version(version)\n\treturn r\n}\n\n// IndexBoost sets a boost a specific index will receive when\n// the query is executed against it.\nfunc (r *SearchRequest) IndexBoost(index string, boost float64) *SearchRequest {\n\tr.searchSource = r.searchSource.IndexBoost(index, boost)\n\treturn r\n}\n\n// Stats groups that this request will be aggregated under.\nfunc (r *SearchRequest) Stats(statsGroup ...string) *SearchRequest {\n\tr.searchSource = r.searchSource.Stats(statsGroup...)\n\treturn r\n}\n\n// FetchSource indicates whether the response should contain the stored\n// _source for every hit.\nfunc (r *SearchRequest) FetchSource(fetchSource bool) *SearchRequest {\n\tr.searchSource = r.searchSource.FetchSource(fetchSource)\n\treturn r\n}\n\n// FetchSourceIncludeExclude specifies that _source should be returned\n// with each hit, where \"include\" and \"exclude\" serve as a simple wildcard\n// matcher that gets applied to its fields\n// (e.g. include := []string{\"obj1.*\",\"obj2.*\"}, exclude := []string{\"description.*\"}).\nfunc (r *SearchRequest) FetchSourceIncludeExclude(include, exclude []string) *SearchRequest {\n\tr.searchSource = r.searchSource.FetchSourceIncludeExclude(include, exclude)\n\treturn r\n}\n\n// FetchSourceContext indicates how the _source should be fetched.\nfunc (r *SearchRequest) FetchSourceContext(fsc *FetchSourceContext) *SearchRequest {\n\tr.searchSource = r.searchSource.FetchSourceContext(fsc)\n\treturn r\n}\n\n// DocValueField adds a docvalue based field to load and return.\n// The field does not have to be stored, but it's recommended to use\n// non analyzed or numeric fields.\nfunc (r *SearchRequest) DocValueField(field string) *SearchRequest {\n\tr.searchSource = r.searchSource.DocvalueField(field)\n\treturn r\n}\n\n// DocValueFieldWithFormat adds a docvalue based field to load and return.\n// The field does not have to be stored, but it's recommended to use\n// non analyzed or numeric fields.\nfunc (r *SearchRequest) DocValueFieldWithFormat(field DocvalueField) *SearchRequest {\n\tr.searchSource = r.searchSource.DocvalueFieldWithFormat(field)\n\treturn r\n}\n\n// DocValueFields adds one or more docvalue based field to load and return.\n// The fields do not have to be stored, but it's recommended to use\n// non analyzed or numeric fields.\nfunc (r *SearchRequest) DocValueFields(fields ...string) *SearchRequest {\n\tr.searchSource = r.searchSource.DocvalueFields(fields...)\n\treturn r\n}\n\n// DocValueFieldsWithFormat adds one or more docvalue based field to load and return.\n// The fields do not have to be stored, but it's recommended to use\n// non analyzed or numeric fields.\nfunc (r *SearchRequest) DocValueFieldsWithFormat(fields ...DocvalueField) *SearchRequest {\n\tr.searchSource = r.searchSource.DocvalueFieldsWithFormat(fields...)\n\treturn r\n}\n\n// StoredField adds a stored field to load and return\n// (note, it must be stored) as part of the search request.\nfunc (r *SearchRequest) StoredField(field string) *SearchRequest {\n\tr.searchSource = r.searchSource.StoredField(field)\n\treturn r\n}\n\n// NoStoredFields indicates that no fields should be loaded,\n// resulting in only id and type to be returned per field.\nfunc (r *SearchRequest) NoStoredFields() *SearchRequest {\n\tr.searchSource = r.searchSource.NoStoredFields()\n\treturn r\n}\n\n// StoredFields adds one or more stored field to load and return\n// (note, they must be stored) as part of the search request.\nfunc (r *SearchRequest) StoredFields(fields ...string) *SearchRequest {\n\tr.searchSource = r.searchSource.StoredFields(fields...)\n\treturn r\n}\n\n// ScriptField adds a script based field to load and return.\n// The field does not have to be stored, but it's recommended\n// to use non analyzed or numeric fields.\nfunc (r *SearchRequest) ScriptField(field *ScriptField) *SearchRequest {\n\tr.searchSource = r.searchSource.ScriptField(field)\n\treturn r\n}\n\n// ScriptFields adds one or more script based field to load and return.\n// The fields do not have to be stored, but it's recommended\n// to use non analyzed or numeric fields.\nfunc (r *SearchRequest) ScriptFields(fields ...*ScriptField) *SearchRequest {\n\tr.searchSource = r.searchSource.ScriptFields(fields...)\n\treturn r\n}\n\n// Sort adds a sort order.\nfunc (r *SearchRequest) Sort(field string, ascending bool) *SearchRequest {\n\tr.searchSource = r.searchSource.Sort(field, ascending)\n\treturn r\n}\n\n// SortWithInfo adds a sort order.\nfunc (r *SearchRequest) SortWithInfo(info SortInfo) *SearchRequest {\n\tr.searchSource = r.searchSource.SortWithInfo(info)\n\treturn r\n}\n\n// SortBy adds a sort order.\nfunc (r *SearchRequest) SortBy(sorter ...Sorter) *SearchRequest {\n\tr.searchSource = r.searchSource.SortBy(sorter...)\n\treturn r\n}\n\n// SearchAfter sets the sort values that indicates which docs this\n// request should \"search after\".\nfunc (r *SearchRequest) SearchAfter(sortValues ...interface{}) *SearchRequest {\n\tr.searchSource = r.searchSource.SearchAfter(sortValues...)\n\treturn r\n}\n\n// Slice allows partitioning the documents in multiple slices.\n// It is e.g. used to slice a scroll operation, supported in\n// Elasticsearch 5.0 or later.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-scroll.html#sliced-scroll\n// for details.\nfunc (r *SearchRequest) Slice(sliceQuery Query) *SearchRequest {\n\tr.searchSource = r.searchSource.Slice(sliceQuery)\n\treturn r\n}\n\n// TrackScores is applied when sorting and controls if scores will be\n// tracked as well. Defaults to false.\nfunc (r *SearchRequest) TrackScores(trackScores bool) *SearchRequest {\n\tr.searchSource = r.searchSource.TrackScores(trackScores)\n\treturn r\n}\n\n// TrackTotalHits indicates if the total hit count for the query should be tracked.\n// Defaults to true.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-track-total-hits.html\n// for details.\nfunc (r *SearchRequest) TrackTotalHits(trackTotalHits interface{}) *SearchRequest {\n\tr.searchSource = r.searchSource.TrackTotalHits(trackTotalHits)\n\treturn r\n}\n\n// Aggregation adds an aggreation to perform as part of the search.\nfunc (r *SearchRequest) Aggregation(name string, aggregation Aggregation) *SearchRequest {\n\tr.searchSource = r.searchSource.Aggregation(name, aggregation)\n\treturn r\n}\n\n// Highlight adds highlighting to the search.\nfunc (r *SearchRequest) Highlight(highlight *Highlight) *SearchRequest {\n\tr.searchSource = r.searchSource.Highlight(highlight)\n\treturn r\n}\n\n// Suggester adds a suggester to the search.\nfunc (r *SearchRequest) Suggester(suggester Suggester) *SearchRequest {\n\tr.searchSource = r.searchSource.Suggester(suggester)\n\treturn r\n}\n\n// Rescorer adds a rescorer to the search.\nfunc (r *SearchRequest) Rescorer(rescore *Rescore) *SearchRequest {\n\tr.searchSource = r.searchSource.Rescorer(rescore)\n\treturn r\n}\n\n// ClearRescorers removes all rescorers from the search.\nfunc (r *SearchRequest) ClearRescorers() *SearchRequest {\n\tr.searchSource = r.searchSource.ClearRescorers()\n\treturn r\n}\n\n// Profile specifies that this search source should activate the\n// Profile API for queries made on it.\nfunc (r *SearchRequest) Profile(profile bool) *SearchRequest {\n\tr.searchSource = r.searchSource.Profile(profile)\n\treturn r\n}\n\n// Collapse adds field collapsing.\nfunc (r *SearchRequest) Collapse(collapse *CollapseBuilder) *SearchRequest {\n\tr.searchSource = r.searchSource.Collapse(collapse)\n\treturn r\n}\n\n// PointInTime specifies an optional PointInTime to be used in the context\n// of this search.\nfunc (s *SearchRequest) PointInTime(pointInTime *PointInTime) *SearchRequest {\n\ts.searchSource = s.searchSource.PointInTime(pointInTime)\n\treturn s\n}\n\n// AllowPartialSearchResults indicates if this request should allow partial\n// results. (If method is not called, will default to the cluster level\n// setting).\nfunc (r *SearchRequest) AllowPartialSearchResults(allow bool) *SearchRequest {\n\tr.allowPartialSearchResults = &allow\n\treturn r\n}\n\n// BatchedReduceSize specifies the number of shard results that should be\n// reduced at once on the coordinating node. This value should be used\n// as a protection mechanism to reduce the memory overhead per search request\n// if the potential number of shards in the request can be large.\nfunc (r *SearchRequest) BatchedReduceSize(size int) *SearchRequest {\n\tr.batchedReduceSize = &size\n\treturn r\n}\n\n// MaxConcurrentShardRequests sets the number of shard requests that should\n// be executed concurrently. This value should be used as a protection\n// mechanism to reduce the number of shard requests fired per high level\n// search request. Searches that hit the entire cluster can be throttled\n// with this number to reduce the cluster load. The default grows with\n// the number of nodes in the cluster but is at most 256.\nfunc (r *SearchRequest) MaxConcurrentShardRequests(size int) *SearchRequest {\n\tr.maxConcurrentShardRequests = &size\n\treturn r\n}\n\n// PreFilterShardSize sets a threshold that enforces a pre-filter roundtrip\n// to pre-filter search shards based on query rewriting if the number of\n// shards the search request expands to exceeds the threshold.\n// This filter roundtrip can limit the number of shards significantly if for\n// instance a shard can not match any documents based on it's rewrite\n// method ie. if date filters are mandatory to match but the shard\n// bounds and the query are disjoint. The default is 128.\nfunc (r *SearchRequest) PreFilterShardSize(size int) *SearchRequest {\n\tr.preFilterShardSize = &size\n\treturn r\n}\n\n// header is used e.g. by MultiSearch to get information about the search header\n// of one SearchRequest.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-multi-search.html\nfunc (r *SearchRequest) header() interface{} {\n\th := make(map[string]interface{})\n\tif r.searchType != \"\" {\n\t\th[\"search_type\"] = r.searchType\n\t}\n\n\tswitch len(r.indices) {\n\tcase 0:\n\tcase 1:\n\t\th[\"index\"] = r.indices[0]\n\tdefault:\n\t\th[\"indices\"] = r.indices\n\t}\n\n\tswitch len(r.types) {\n\tcase 0:\n\tcase 1:\n\t\th[\"type\"] = r.types[0]\n\tdefault:\n\t\th[\"types\"] = r.types\n\t}\n\n\tif r.routing != nil && *r.routing != \"\" {\n\t\th[\"routing\"] = *r.routing\n\t}\n\tif r.preference != nil && *r.preference != \"\" {\n\t\th[\"preference\"] = *r.preference\n\t}\n\tif r.requestCache != nil {\n\t\th[\"request_cache\"] = *r.requestCache\n\t}\n\tif r.ignoreUnavailable != nil {\n\t\th[\"ignore_unavailable\"] = *r.ignoreUnavailable\n\t}\n\tif r.allowNoIndices != nil {\n\t\th[\"allow_no_indices\"] = *r.allowNoIndices\n\t}\n\tif r.expandWildcards != \"\" {\n\t\th[\"expand_wildcards\"] = r.expandWildcards\n\t}\n\tif v := r.allowPartialSearchResults; v != nil {\n\t\th[\"allow_partial_search_results\"] = *v\n\t}\n\tif r.scroll != \"\" {\n\t\th[\"scroll\"] = r.scroll\n\t}\n\n\treturn h\n}\n\n// Body allows to access the search body of the request, as generated by the DSL.\n// Notice that Body is read-only. You must not change the request body.\n//\n// Body is used e.g. by MultiSearch to get information about the search body\n// of one SearchRequest.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-multi-search.html\nfunc (r *SearchRequest) Body() (string, error) {\n\tif r.source == nil {\n\t\t// Default: No custom source specified\n\t\tsrc, err := r.searchSource.Source()\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tbody, err := json.Marshal(src)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn string(body), nil\n\t}\n\tswitch t := r.source.(type) {\n\tdefault:\n\t\tbody, err := json.Marshal(r.source)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn string(body), nil\n\tcase *SearchSource:\n\t\tsrc, err := t.Source()\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tbody, err := json.Marshal(src)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn string(body), nil\n\tcase json.RawMessage:\n\t\treturn string(t), nil\n\tcase *json.RawMessage:\n\t\treturn string(*t), nil\n\tcase string:\n\t\treturn t, nil\n\tcase *string:\n\t\tif t != nil {\n\t\t\treturn *t, nil\n\t\t}\n\t\treturn \"{}\", nil\n\t}\n}\n\n// source returns the search source. It is used by Reindex.\nfunc (r *SearchRequest) sourceAsMap() (interface{}, error) {\n\tif r.source == nil {\n\t\t// Default: No custom source specified\n\t\treturn r.searchSource.Source()\n\t}\n\tswitch t := r.source.(type) {\n\tdefault:\n\t\tbody, err := json.Marshal(r.source)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn RawStringQuery(body), nil\n\tcase *SearchSource:\n\t\treturn t.Source()\n\tcase json.RawMessage:\n\t\treturn RawStringQuery(string(t)), nil\n\tcase *json.RawMessage:\n\t\treturn RawStringQuery(string(*t)), nil\n\tcase string:\n\t\treturn RawStringQuery(t), nil\n\tcase *string:\n\t\tif t != nil {\n\t\t\treturn RawStringQuery(*t), nil\n\t\t}\n\t\treturn RawStringQuery(\"{}\"), nil\n\t}\n}\n"
  },
  {
    "path": "search_request_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t_ \"net/http\"\n\t\"testing\"\n)\n\nfunc TestSearchRequestIndex(t *testing.T) {\n\tbuilder := NewSearchRequest().Index(\"test\")\n\tdata, err := json.Marshal(builder.header())\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"index\":\"test\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchRequestIndices(t *testing.T) {\n\tbuilder := NewSearchRequest().Index(\"test\", \"test2\")\n\tdata, err := json.Marshal(builder.header())\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"indices\":[\"test\",\"test2\"]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchRequestHasIndices(t *testing.T) {\n\tbuilder := NewSearchRequest()\n\tif builder.HasIndices() {\n\t\tt.Errorf(\"expected HasIndices to return true; got %v\", builder.HasIndices())\n\t}\n\tbuilder = builder.Index(\"test\", \"test2\")\n\tif !builder.HasIndices() {\n\t\tt.Errorf(\"expected HasIndices to return false; got %v\", builder.HasIndices())\n\t}\n}\n\nfunc TestSearchRequestIgnoreUnavailable(t *testing.T) {\n\tbuilder := NewSearchRequest().Index(\"test\").IgnoreUnavailable(true)\n\tdata, err := json.Marshal(builder.header())\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"ignore_unavailable\":true,\"index\":\"test\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_shards.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SearchShardsService returns the indices and shards that a search request would be executed against.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-shards.html\ntype SearchShardsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\trouting           string\n\tlocal             *bool\n\tpreference        string\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n}\n\n// NewSearchShardsService creates a new SearchShardsService.\nfunc NewSearchShardsService(client *Client) *SearchShardsService {\n\treturn &SearchShardsService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SearchShardsService) Pretty(pretty bool) *SearchShardsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SearchShardsService) Human(human bool) *SearchShardsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SearchShardsService) ErrorTrace(errorTrace bool) *SearchShardsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SearchShardsService) FilterPath(filterPath ...string) *SearchShardsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SearchShardsService) Header(name string, value string) *SearchShardsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SearchShardsService) Headers(headers http.Header) *SearchShardsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index sets the names of the indices to restrict the results.\nfunc (s *SearchShardsService) Index(index ...string) *SearchShardsService {\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n//A boolean value whether to read the cluster state locally in order to\n//determine where shards are allocated instead of using the Master node’s cluster state.\nfunc (s *SearchShardsService) Local(local bool) *SearchShardsService {\n\ts.local = &local\n\treturn s\n}\n\n// Routing sets a specific routing value.\nfunc (s *SearchShardsService) Routing(routing string) *SearchShardsService {\n\ts.routing = routing\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be performed on (default: random).\nfunc (s *SearchShardsService) Preference(preference string) *SearchShardsService {\n\ts.preference = preference\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether the specified concrete indices\n// should be ignored when unavailable (missing or closed).\nfunc (s *SearchShardsService) IgnoreUnavailable(ignoreUnavailable bool) *SearchShardsService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes `_all` string\n// or when no indices have been specified).\nfunc (s *SearchShardsService) AllowNoIndices(allowNoIndices bool) *SearchShardsService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *SearchShardsService) ExpandWildcards(expandWildcards string) *SearchShardsService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SearchShardsService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/{index}/_search_shards\", map[string]string{\n\t\t\"index\": strings.Join(s.index, \",\"),\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif s.local != nil {\n\t\tparams.Set(\"local\", fmt.Sprintf(\"%v\", *s.local))\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif s.ignoreUnavailable != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprintf(\"%v\", *s.ignoreUnavailable))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SearchShardsService) Validate() error {\n\tvar invalid []string\n\tif len(s.index) < 1 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *SearchShardsService) Do(ctx context.Context) (*SearchShardsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SearchShardsResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// SearchShardsResponse is the response of SearchShardsService.Do.\ntype SearchShardsResponse struct {\n\tNodes   map[string]interface{}              `json:\"nodes\"`\n\tIndices map[string]interface{}              `json:\"indices\"`\n\tShards  [][]*SearchShardsResponseShardsInfo `json:\"shards\"`\n}\n\ntype SearchShardsResponseShardsInfo struct {\n\tIndex                    string          `json:\"index\"`\n\tNode                     string          `json:\"node\"`\n\tPrimary                  bool            `json:\"primary\"`\n\tShard                    uint            `json:\"shard\"`\n\tState                    string          `json:\"state\"`\n\tAllocationId             *AllocationId   `json:\"allocation_id,omitempty\"`\n\tRelocatingNode           string          `json:\"relocating_node\"`\n\tExpectedShardSizeInBytes int64           `json:\"expected_shard_size_in_bytes,omitempty\"`\n\tRecoverySource           *RecoverySource `json:\"recovery_source,omitempty\"`\n\tUnassignedInfo           *UnassignedInfo `json:\"unassigned_info,omitempty\"`\n}\n\ntype RecoverySource struct {\n\tType string `json:\"type\"`\n\t// TODO add missing fields here based on the Type\n}\n\ntype AllocationId struct {\n\tId           string `json:\"id\"`\n\tRelocationId string `json:\"relocation_id,omitempty\"`\n}\n\ntype UnassignedInfo struct {\n\tReason           string     `json:\"reason\"`\n\tAt               *time.Time `json:\"at,omitempty\"`\n\tFailedAttempts   int        `json:\"failed_attempts,omitempty\"`\n\tDelayed          bool       `json:\"delayed\"`\n\tDetails          string     `json:\"details,omitempty\"`\n\tAllocationStatus string     `json:\"allocation_status\"`\n}\n"
  },
  {
    "path": "search_shards_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestSearchShards(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\tindexes := []string{testIndexName}\n\n\tshardsInfo, err := client.SearchShards(indexes...).\n\t\tPretty(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif shardsInfo == nil {\n\t\tt.Fatal(\"expected to return an shards information\")\n\t}\n\tif len(shardsInfo.Shards) < 1 {\n\t\tt.Fatal(\"expected to return minimun one shard information\")\n\t}\n\tif shardsInfo.Shards[0][0].Index != testIndexName {\n\t\tt.Fatal(\"expected to return shard info concerning requested index\")\n\t}\n\tif shardsInfo.Shards[0][0].State != \"STARTED\" {\n\t\tt.Fatal(\"expected to return STARTED status for running shards\")\n\t}\n}\n"
  },
  {
    "path": "search_source.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// SearchSource enables users to build the search source.\n// It resembles the SearchSourceBuilder in Elasticsearch.\ntype SearchSource struct {\n\tquery                    Query                  // query\n\tpostQuery                Query                  // post_filter\n\tsliceQuery               Query                  // slice\n\tfrom                     int                    // from\n\tsize                     int                    // size\n\texplain                  *bool                  // explain\n\tversion                  *bool                  // version\n\tseqNoAndPrimaryTerm      *bool                  // seq_no_primary_term\n\tsorters                  []Sorter               // sort\n\ttrackScores              *bool                  // track_scores\n\ttrackTotalHits           interface{}            // track_total_hits\n\tsearchAfterSortValues    []interface{}          // search_after\n\tminScore                 *float64               // min_score\n\ttimeout                  string                 // timeout\n\tterminateAfter           *int                   // terminate_after\n\tstoredFieldNames         []string               // stored_fields\n\tdocvalueFields           DocvalueFields         // docvalue_fields\n\tscriptFields             []*ScriptField         // script_fields\n\tfetchSourceContext       *FetchSourceContext    // _source\n\taggregations             map[string]Aggregation // aggregations / aggs\n\thighlight                *Highlight             // highlight\n\tglobalSuggestText        string\n\tsuggesters               []Suggester // suggest\n\trescores                 []*Rescore  // rescore\n\tdefaultRescoreWindowSize *int\n\tindexBoosts              IndexBoosts // indices_boost\n\tstats                    []string    // stats\n\tinnerHits                map[string]*InnerHit\n\tcollapse                 *CollapseBuilder // collapse\n\tprofile                  bool             // profile\n\t// TODO extBuilders []SearchExtBuilder // ext\n\tpointInTime     *PointInTime // pit\n\truntimeMappings RuntimeMappings\n}\n\n// NewSearchSource initializes a new SearchSource.\nfunc NewSearchSource() *SearchSource {\n\treturn &SearchSource{\n\t\tfrom:         -1,\n\t\tsize:         -1,\n\t\taggregations: make(map[string]Aggregation),\n\t\tinnerHits:    make(map[string]*InnerHit),\n\t}\n}\n\n// Query sets the query to use with this search source.\nfunc (s *SearchSource) Query(query Query) *SearchSource {\n\ts.query = query\n\treturn s\n}\n\n// Profile specifies that this search source should activate the\n// Profile API for queries made on it.\nfunc (s *SearchSource) Profile(profile bool) *SearchSource {\n\ts.profile = profile\n\treturn s\n}\n\n// PostFilter will be executed after the query has been executed and\n// only affects the search hits, not the aggregations.\n// This filter is always executed as the last filtering mechanism.\nfunc (s *SearchSource) PostFilter(postFilter Query) *SearchSource {\n\ts.postQuery = postFilter\n\treturn s\n}\n\n// Slice allows partitioning the documents in multiple slices.\n// It is e.g. used to slice a scroll operation, supported in\n// Elasticsearch 5.0 or later.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-scroll.html#sliced-scroll\n// for details.\nfunc (s *SearchSource) Slice(sliceQuery Query) *SearchSource {\n\ts.sliceQuery = sliceQuery\n\treturn s\n}\n\n// From index to start the search from. Defaults to 0.\nfunc (s *SearchSource) From(from int) *SearchSource {\n\ts.from = from\n\treturn s\n}\n\n// Size is the number of search hits to return. Defaults to 10.\nfunc (s *SearchSource) Size(size int) *SearchSource {\n\ts.size = size\n\treturn s\n}\n\n// MinScore sets the minimum score below which docs will be filtered out.\nfunc (s *SearchSource) MinScore(minScore float64) *SearchSource {\n\ts.minScore = &minScore\n\treturn s\n}\n\n// Explain indicates whether each search hit should be returned with\n// an explanation of the hit (ranking).\nfunc (s *SearchSource) Explain(explain bool) *SearchSource {\n\ts.explain = &explain\n\treturn s\n}\n\n// Version indicates whether each search hit should be returned with\n// a version associated to it.\nfunc (s *SearchSource) Version(version bool) *SearchSource {\n\ts.version = &version\n\treturn s\n}\n\n// SeqNoAndPrimaryTerm indicates whether SearchHits should be returned with the\n// sequence number and primary term of the last modification of the document.\nfunc (s *SearchSource) SeqNoAndPrimaryTerm(enabled bool) *SearchSource {\n\ts.seqNoAndPrimaryTerm = &enabled\n\treturn s\n}\n\n// Timeout controls how long a search is allowed to take, e.g. \"1s\" or \"500ms\".\nfunc (s *SearchSource) Timeout(timeout string) *SearchSource {\n\ts.timeout = timeout\n\treturn s\n}\n\n// TimeoutInMillis controls how many milliseconds a search is allowed\n// to take before it is canceled.\nfunc (s *SearchSource) TimeoutInMillis(timeoutInMillis int) *SearchSource {\n\ts.timeout = fmt.Sprintf(\"%dms\", timeoutInMillis)\n\treturn s\n}\n\n// TerminateAfter specifies the maximum number of documents to collect for\n// each shard, upon reaching which the query execution will terminate early.\nfunc (s *SearchSource) TerminateAfter(terminateAfter int) *SearchSource {\n\ts.terminateAfter = &terminateAfter\n\treturn s\n}\n\n// Sort adds a sort order.\nfunc (s *SearchSource) Sort(field string, ascending bool) *SearchSource {\n\ts.sorters = append(s.sorters, SortInfo{Field: field, Ascending: ascending})\n\treturn s\n}\n\n// SortWithInfo adds a sort order.\nfunc (s *SearchSource) SortWithInfo(info SortInfo) *SearchSource {\n\ts.sorters = append(s.sorters, info)\n\treturn s\n}\n\n// SortBy\tadds a sort order.\nfunc (s *SearchSource) SortBy(sorter ...Sorter) *SearchSource {\n\ts.sorters = append(s.sorters, sorter...)\n\treturn s\n}\n\nfunc (s *SearchSource) hasSort() bool {\n\treturn len(s.sorters) > 0\n}\n\n// TrackScores is applied when sorting and controls if scores will be\n// tracked as well. Defaults to false.\nfunc (s *SearchSource) TrackScores(trackScores bool) *SearchSource {\n\ts.trackScores = &trackScores\n\treturn s\n}\n\n// TrackTotalHits controls how the total number of hits should be tracked.\n// Defaults to 10000 which will count the total hit accurately up to 10,000 hits.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-track-total-hits.html\n// for details.\nfunc (s *SearchSource) TrackTotalHits(trackTotalHits interface{}) *SearchSource {\n\ts.trackTotalHits = trackTotalHits\n\treturn s\n}\n\n// SearchAfter allows a different form of pagination by using a live cursor,\n// using the results of the previous page to help the retrieval of the next.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-search-after.html\nfunc (s *SearchSource) SearchAfter(sortValues ...interface{}) *SearchSource {\n\ts.searchAfterSortValues = append(s.searchAfterSortValues, sortValues...)\n\treturn s\n}\n\n// Aggregation adds an aggreation to perform as part of the search.\nfunc (s *SearchSource) Aggregation(name string, aggregation Aggregation) *SearchSource {\n\ts.aggregations[name] = aggregation\n\treturn s\n}\n\n// DefaultRescoreWindowSize sets the rescore window size for rescores\n// that don't specify their window.\nfunc (s *SearchSource) DefaultRescoreWindowSize(defaultRescoreWindowSize int) *SearchSource {\n\ts.defaultRescoreWindowSize = &defaultRescoreWindowSize\n\treturn s\n}\n\n// Highlight adds highlighting to the search.\nfunc (s *SearchSource) Highlight(highlight *Highlight) *SearchSource {\n\ts.highlight = highlight\n\treturn s\n}\n\n// Highlighter returns the highlighter.\nfunc (s *SearchSource) Highlighter() *Highlight {\n\tif s.highlight == nil {\n\t\ts.highlight = NewHighlight()\n\t}\n\treturn s.highlight\n}\n\n// GlobalSuggestText defines the global text to use with all suggesters.\n// This avoids repetition.\nfunc (s *SearchSource) GlobalSuggestText(text string) *SearchSource {\n\ts.globalSuggestText = text\n\treturn s\n}\n\n// Suggester adds a suggester to the search.\nfunc (s *SearchSource) Suggester(suggester Suggester) *SearchSource {\n\ts.suggesters = append(s.suggesters, suggester)\n\treturn s\n}\n\n// Rescorer adds a rescorer to the search.\nfunc (s *SearchSource) Rescorer(rescore *Rescore) *SearchSource {\n\ts.rescores = append(s.rescores, rescore)\n\treturn s\n}\n\n// ClearRescorers removes all rescorers from the search.\nfunc (s *SearchSource) ClearRescorers() *SearchSource {\n\ts.rescores = make([]*Rescore, 0)\n\treturn s\n}\n\n// FetchSource indicates whether the response should contain the stored\n// _source for every hit.\nfunc (s *SearchSource) FetchSource(fetchSource bool) *SearchSource {\n\tif s.fetchSourceContext == nil {\n\t\ts.fetchSourceContext = NewFetchSourceContext(fetchSource)\n\t} else {\n\t\ts.fetchSourceContext.SetFetchSource(fetchSource)\n\t}\n\treturn s\n}\n\n// FetchSourceContext indicates how the _source should be fetched.\nfunc (s *SearchSource) FetchSourceContext(fetchSourceContext *FetchSourceContext) *SearchSource {\n\ts.fetchSourceContext = fetchSourceContext\n\treturn s\n}\n\n// FetchSourceIncludeExclude specifies that _source should be returned\n// with each hit, where \"include\" and \"exclude\" serve as a simple wildcard\n// matcher that gets applied to its fields\n// (e.g. include := []string{\"obj1.*\",\"obj2.*\"}, exclude := []string{\"description.*\"}).\nfunc (s *SearchSource) FetchSourceIncludeExclude(include, exclude []string) *SearchSource {\n\ts.fetchSourceContext = NewFetchSourceContext(true).\n\t\tInclude(include...).\n\t\tExclude(exclude...)\n\treturn s\n}\n\n// NoStoredFields indicates that no fields should be loaded, resulting in only\n// id and type to be returned per field.\nfunc (s *SearchSource) NoStoredFields() *SearchSource {\n\ts.storedFieldNames = []string{}\n\treturn s\n}\n\n// StoredField adds a single field to load and return (note, must be stored) as\n// part of the search request. If none are specified, the source of the\n// document will be returned.\nfunc (s *SearchSource) StoredField(storedFieldName string) *SearchSource {\n\ts.storedFieldNames = append(s.storedFieldNames, storedFieldName)\n\treturn s\n}\n\n// StoredFields\tsets the fields to load and return as part of the search request.\n// If none are specified, the source of the document will be returned.\nfunc (s *SearchSource) StoredFields(storedFieldNames ...string) *SearchSource {\n\ts.storedFieldNames = append(s.storedFieldNames, storedFieldNames...)\n\treturn s\n}\n\n// DocvalueField adds a single field to load from the field data cache\n// and return as part of the search request.\nfunc (s *SearchSource) DocvalueField(fieldDataField string) *SearchSource {\n\ts.docvalueFields = append(s.docvalueFields, DocvalueField{Field: fieldDataField})\n\treturn s\n}\n\n// DocvalueField adds a single docvalue field to load from the field data cache\n// and return as part of the search request.\nfunc (s *SearchSource) DocvalueFieldWithFormat(fieldDataFieldWithFormat DocvalueField) *SearchSource {\n\ts.docvalueFields = append(s.docvalueFields, fieldDataFieldWithFormat)\n\treturn s\n}\n\n// DocvalueFields adds one or more fields to load from the field data cache\n// and return as part of the search request.\nfunc (s *SearchSource) DocvalueFields(docvalueFields ...string) *SearchSource {\n\tfor _, f := range docvalueFields {\n\t\ts.docvalueFields = append(s.docvalueFields, DocvalueField{Field: f})\n\t}\n\treturn s\n}\n\n// DocvalueFields adds one or more docvalue fields to load from the field data cache\n// and return as part of the search request.\nfunc (s *SearchSource) DocvalueFieldsWithFormat(docvalueFields ...DocvalueField) *SearchSource {\n\ts.docvalueFields = append(s.docvalueFields, docvalueFields...)\n\treturn s\n}\n\n// ScriptField adds a single script field with the provided script.\nfunc (s *SearchSource) ScriptField(scriptField *ScriptField) *SearchSource {\n\ts.scriptFields = append(s.scriptFields, scriptField)\n\treturn s\n}\n\n// ScriptFields adds one or more script fields with the provided scripts.\nfunc (s *SearchSource) ScriptFields(scriptFields ...*ScriptField) *SearchSource {\n\ts.scriptFields = append(s.scriptFields, scriptFields...)\n\treturn s\n}\n\n// IndexBoost sets the boost that a specific index will receive when the\n// query is executed against it.\nfunc (s *SearchSource) IndexBoost(index string, boost float64) *SearchSource {\n\ts.indexBoosts = append(s.indexBoosts, IndexBoost{Index: index, Boost: boost})\n\treturn s\n}\n\n// IndexBoosts sets the boosts for specific indices.\nfunc (s *SearchSource) IndexBoosts(boosts ...IndexBoost) *SearchSource {\n\ts.indexBoosts = append(s.indexBoosts, boosts...)\n\treturn s\n}\n\n// Stats group this request will be aggregated under.\nfunc (s *SearchSource) Stats(statsGroup ...string) *SearchSource {\n\ts.stats = append(s.stats, statsGroup...)\n\treturn s\n}\n\n// InnerHit adds an inner hit to return with the result.\nfunc (s *SearchSource) InnerHit(name string, innerHit *InnerHit) *SearchSource {\n\ts.innerHits[name] = innerHit\n\treturn s\n}\n\n// Collapse adds field collapsing.\nfunc (s *SearchSource) Collapse(collapse *CollapseBuilder) *SearchSource {\n\ts.collapse = collapse\n\treturn s\n}\n\n// PointInTime specifies an optional PointInTime to be used in the context\n// of this search.\nfunc (s *SearchSource) PointInTime(pointInTime *PointInTime) *SearchSource {\n\ts.pointInTime = pointInTime\n\treturn s\n}\n\n// RuntimeMappings specifies optional runtime mappings.\nfunc (s *SearchSource) RuntimeMappings(runtimeMappings RuntimeMappings) *SearchSource {\n\ts.runtimeMappings = runtimeMappings\n\treturn s\n}\n\n// Source returns the serializable JSON for the source builder.\nfunc (s *SearchSource) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tif s.from != -1 {\n\t\tsource[\"from\"] = s.from\n\t}\n\tif s.size != -1 {\n\t\tsource[\"size\"] = s.size\n\t}\n\tif s.timeout != \"\" {\n\t\tsource[\"timeout\"] = s.timeout\n\t}\n\tif s.terminateAfter != nil {\n\t\tsource[\"terminate_after\"] = *s.terminateAfter\n\t}\n\tif s.query != nil {\n\t\tsrc, err := s.query.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"query\"] = src\n\t}\n\tif s.postQuery != nil {\n\t\tsrc, err := s.postQuery.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"post_filter\"] = src\n\t}\n\tif s.minScore != nil {\n\t\tsource[\"min_score\"] = *s.minScore\n\t}\n\tif s.version != nil {\n\t\tsource[\"version\"] = *s.version\n\t}\n\tif s.explain != nil {\n\t\tsource[\"explain\"] = *s.explain\n\t}\n\tif s.profile {\n\t\tsource[\"profile\"] = s.profile\n\t}\n\tif s.fetchSourceContext != nil {\n\t\tsrc, err := s.fetchSourceContext.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"_source\"] = src\n\t}\n\tif s.storedFieldNames != nil {\n\t\tswitch len(s.storedFieldNames) {\n\t\tcase 1:\n\t\t\tsource[\"stored_fields\"] = s.storedFieldNames[0]\n\t\tdefault:\n\t\t\tsource[\"stored_fields\"] = s.storedFieldNames\n\t\t}\n\t}\n\tif len(s.docvalueFields) > 0 {\n\t\tsrc, err := s.docvalueFields.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"docvalue_fields\"] = src\n\t}\n\tif len(s.scriptFields) > 0 {\n\t\tsfmap := make(map[string]interface{})\n\t\tfor _, scriptField := range s.scriptFields {\n\t\t\tsrc, err := scriptField.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tsfmap[scriptField.FieldName] = src\n\t\t}\n\t\tsource[\"script_fields\"] = sfmap\n\t}\n\tif len(s.sorters) > 0 {\n\t\tvar sortarr []interface{}\n\t\tfor _, sorter := range s.sorters {\n\t\t\tsrc, err := sorter.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tsortarr = append(sortarr, src)\n\t\t}\n\t\tsource[\"sort\"] = sortarr\n\t}\n\tif v := s.trackScores; v != nil {\n\t\tsource[\"track_scores\"] = *v\n\t}\n\tif v := s.trackTotalHits; v != nil {\n\t\tsource[\"track_total_hits\"] = v\n\t}\n\tif len(s.searchAfterSortValues) > 0 {\n\t\tsource[\"search_after\"] = s.searchAfterSortValues\n\t}\n\tif s.sliceQuery != nil {\n\t\tsrc, err := s.sliceQuery.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"slice\"] = src\n\t}\n\tif len(s.indexBoosts) > 0 {\n\t\tsrc, err := s.indexBoosts.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"indices_boost\"] = src\n\t}\n\tif len(s.aggregations) > 0 {\n\t\taggsMap := make(map[string]interface{})\n\t\tfor name, aggregate := range s.aggregations {\n\t\t\tsrc, err := aggregate.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\taggsMap[name] = src\n\t\t}\n\t\tsource[\"aggregations\"] = aggsMap\n\t}\n\tif s.highlight != nil {\n\t\tsrc, err := s.highlight.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"highlight\"] = src\n\t}\n\tif len(s.suggesters) > 0 {\n\t\tsuggesters := make(map[string]interface{})\n\t\tfor _, s := range s.suggesters {\n\t\t\tsrc, err := s.Source(false)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tsuggesters[s.Name()] = src\n\t\t}\n\t\tif s.globalSuggestText != \"\" {\n\t\t\tsuggesters[\"text\"] = s.globalSuggestText\n\t\t}\n\t\tsource[\"suggest\"] = suggesters\n\t}\n\tif len(s.rescores) > 0 {\n\t\t// Strip empty rescores from request\n\t\tvar rescores []*Rescore\n\t\tfor _, r := range s.rescores {\n\t\t\tif !r.IsEmpty() {\n\t\t\t\trescores = append(rescores, r)\n\t\t\t}\n\t\t}\n\t\tif len(rescores) == 1 {\n\t\t\trescores[0].defaultRescoreWindowSize = s.defaultRescoreWindowSize\n\t\t\tsrc, err := rescores[0].Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tsource[\"rescore\"] = src\n\t\t} else {\n\t\t\tvar slice []interface{}\n\t\t\tfor _, r := range rescores {\n\t\t\t\tr.defaultRescoreWindowSize = s.defaultRescoreWindowSize\n\t\t\t\tsrc, err := r.Source()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tslice = append(slice, src)\n\t\t\t}\n\t\t\tsource[\"rescore\"] = slice\n\t\t}\n\t}\n\tif len(s.stats) > 0 {\n\t\tsource[\"stats\"] = s.stats\n\t}\n\t// TODO ext builders\n\n\tif s.collapse != nil {\n\t\tsrc, err := s.collapse.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"collapse\"] = src\n\t}\n\n\tif v := s.seqNoAndPrimaryTerm; v != nil {\n\t\tsource[\"seq_no_primary_term\"] = *v\n\t}\n\n\tif len(s.innerHits) > 0 {\n\t\t// Top-level inner hits\n\t\t// See http://www.elastic.co/guide/en/elasticsearch/reference/1.5/search-request-inner-hits.html#top-level-inner-hits\n\t\t// \"inner_hits\": {\n\t\t//   \"<inner_hits_name>\": {\n\t\t//     \"<path|type>\": {\n\t\t//       \"<path-to-nested-object-field|child-or-parent-type>\": {\n\t\t//         <inner_hits_body>,\n\t\t//         [,\"inner_hits\" : { [<sub_inner_hits>]+ } ]?\n\t\t//       }\n\t\t//     }\n\t\t//   },\n\t\t//   [,\"<inner_hits_name_2>\" : { ... } ]*\n\t\t// }\n\t\tm := make(map[string]interface{})\n\t\tfor name, hit := range s.innerHits {\n\t\t\tif hit.path != \"\" {\n\t\t\t\tsrc, err := hit.Source()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tpath := make(map[string]interface{})\n\t\t\t\tpath[hit.path] = src\n\t\t\t\tm[name] = map[string]interface{}{\n\t\t\t\t\t\"path\": path,\n\t\t\t\t}\n\t\t\t} else if hit.typ != \"\" {\n\t\t\t\tsrc, err := hit.Source()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\ttyp := make(map[string]interface{})\n\t\t\t\ttyp[hit.typ] = src\n\t\t\t\tm[name] = map[string]interface{}{\n\t\t\t\t\t\"type\": typ,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// TODO the Java client throws here, because either path or typ must be specified\n\t\t\t\t_ = m\n\t\t\t}\n\t\t}\n\t\tsource[\"inner_hits\"] = m\n\t}\n\n\t// Point in Time\n\tif s.pointInTime != nil {\n\t\tsrc, err := s.pointInTime.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"pit\"] = src\n\t}\n\n\tif s.runtimeMappings != nil {\n\t\tsrc, err := s.runtimeMappings.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"runtime_mappings\"] = src\n\t}\n\n\treturn source, nil\n}\n\n// MarshalJSON enables serializing the type as JSON.\nfunc (q *SearchSource) MarshalJSON() ([]byte, error) {\n\tif q == nil {\n\t\treturn nilByte, nil\n\t}\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn json.Marshal(src)\n}\n\n// -- IndexBoosts --\n\n// IndexBoost specifies an index by some boost factor.\ntype IndexBoost struct {\n\tIndex string\n\tBoost float64\n}\n\n// Source generates a JSON-serializable output for IndexBoost.\nfunc (b IndexBoost) Source() (interface{}, error) {\n\treturn map[string]interface{}{\n\t\tb.Index: b.Boost,\n\t}, nil\n}\n\n// IndexBoosts is a slice of IndexBoost entities.\ntype IndexBoosts []IndexBoost\n\n// Source generates a JSON-serializable output for IndexBoosts.\nfunc (b IndexBoosts) Source() (interface{}, error) {\n\tvar boosts []interface{}\n\tfor _, ib := range b {\n\t\tsrc, err := ib.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tboosts = append(boosts, src)\n\t}\n\treturn boosts, nil\n}\n"
  },
  {
    "path": "search_source_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSearchSourceMatchAllQuery(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceMarshalJSON(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ)\n\tdata, err := builder.MarshalJSON()\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\nfunc TestSearchSourceNoStoredFields(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).NoStoredFields()\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}},\"stored_fields\":[]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceStoredFields(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).StoredFields(\"message\", \"tags\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}},\"stored_fields\":[\"message\",\"tags\"]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceFetchSourceDisabled(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).FetchSource(false)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_source\":false,\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceFetchSourceByWildcards(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tfsc := NewFetchSourceContext(true).Include(\"obj1.*\", \"obj2.*\").Exclude(\"*.description\")\n\tbuilder := NewSearchSource().Query(matchAllQ).FetchSourceContext(fsc)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_source\":{\"excludes\":[\"*.description\"],\"includes\":[\"obj1.*\",\"obj2.*\"]},\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceDocvalueFields(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).\n\t\tDocvalueFields(\"test1\", \"test2\").\n\t\tDocvalueFieldsWithFormat(\n\t\t\tDocvalueField{Field: \"test3\", Format: \"date\"},\n\t\t\tDocvalueField{Field: \"test4\", Format: \"epoch_millis\"},\n\t\t)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"docvalue_fields\":[\"test1\",\"test2\",{\"field\":\"test3\",\"format\":\"date\"},{\"field\":\"test4\",\"format\":\"epoch_millis\"}],\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceScriptFields(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tsf1 := NewScriptField(\"test1\", NewScript(\"doc['my_field_name'].value * 2\"))\n\tsf2 := NewScriptField(\"test2\", NewScript(\"doc['my_field_name'].value * factor\").Param(\"factor\", 3.1415927))\n\tbuilder := NewSearchSource().Query(matchAllQ).ScriptFields(sf1, sf2)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}},\"script_fields\":{\"test1\":{\"script\":{\"source\":\"doc['my_field_name'].value * 2\"}},\"test2\":{\"script\":{\"params\":{\"factor\":3.1415927},\"source\":\"doc['my_field_name'].value * factor\"}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourcePostFilter(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tpf := NewTermQuery(\"tag\", \"important\")\n\tbuilder := NewSearchSource().Query(matchAllQ).PostFilter(pf)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"post_filter\":{\"term\":{\"tag\":\"important\"}},\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceHighlight(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\thl := NewHighlight().Field(\"content\")\n\tbuilder := NewSearchSource().Query(matchAllQ).Highlight(hl)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"highlight\":{\"fields\":{\"content\":{}}},\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceRescoring(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\trescorerQuery := NewMatchPhraseQuery(\"field1\", \"the quick brown fox\").Slop(2)\n\trescorer := NewQueryRescorer(rescorerQuery)\n\trescorer = rescorer.QueryWeight(0.7)\n\trescorer = rescorer.RescoreQueryWeight(1.2)\n\trescore := NewRescore().WindowSize(50).Rescorer(rescorer)\n\tbuilder := NewSearchSource().Query(matchAllQ).Rescorer(rescore)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}},\"rescore\":{\"query\":{\"query_weight\":0.7,\"rescore_query\":{\"match_phrase\":{\"field1\":{\"query\":\"the quick brown fox\",\"slop\":2}}},\"rescore_query_weight\":1.2},\"window_size\":50}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceIndexBoost(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).IndexBoost(\"index1\", 1.4).IndexBoost(\"index2\", 1.3)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"indices_boost\":[{\"index1\":1.4},{\"index2\":1.3}],\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceMixDifferentSorters(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).\n\t\tSort(\"a\", false).\n\t\tSortWithInfo(SortInfo{Field: \"b\", Ascending: true}).\n\t\tSortBy(NewScriptSort(NewScript(\"doc['field_name'].value * factor\").Param(\"factor\", 1.1), \"number\"))\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}},\"sort\":[{\"a\":{\"order\":\"desc\"}},{\"b\":{\"order\":\"asc\"}},{\"_script\":{\"order\":\"asc\",\"script\":{\"params\":{\"factor\":1.1},\"source\":\"doc['field_name'].value * factor\"},\"type\":\"number\"}}]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceInnerHits(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).\n\t\tInnerHit(\"comments\", NewInnerHit().Type(\"comment\").Query(NewMatchQuery(\"user\", \"olivere\"))).\n\t\tInnerHit(\"views\", NewInnerHit().Path(\"view\"))\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"inner_hits\":{\"comments\":{\"type\":{\"comment\":{\"query\":{\"match\":{\"user\":{\"query\":\"olivere\"}}}}}},\"views\":{\"path\":{\"view\":{}}}},\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceSearchAfter(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).SearchAfter(1463538857, \"tweet#654323\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}},\"search_after\":[1463538857,\"tweet#654323\"]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceProfiledQuery(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).Profile(true)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"profile\":true,\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceSeqNoAndPrimaryTerm(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).SeqNoAndPrimaryTerm(true)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}},\"seq_no_primary_term\":true}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourcePointInTime(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).PointInTime(\n\t\tNewPointInTimeWithKeepAlive(\"pit_id\", \"2m\"),\n\t)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"pit\":{\"id\":\"pit_id\",\"keep_alive\":\"2m\"},\"query\":{\"match_all\":{}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSearchSourceRuntimeMappings(t *testing.T) {\n\tmatchAllQ := NewMatchAllQuery()\n\tbuilder := NewSearchSource().Query(matchAllQ).RuntimeMappings(RuntimeMappings{\n\t\t\"day_of_week\": map[string]interface{}{\n\t\t\t\"type\": \"keyword\",\n\t\t},\n\t})\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"query\":{\"match_all\":{}},\"runtime_mappings\":{\"day_of_week\":{\"type\":\"keyword\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_suggester_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestTermSuggester(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) // AndLog(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\ttsName := \"my-suggestions\"\n\tts := NewTermSuggester(tsName)\n\tts = ts.Text(\"Goolang\")\n\tts = ts.Field(\"message\")\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tSuggester(ts).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Suggest == nil {\n\t\tt.Errorf(\"expected SearchResult.Suggest != nil; got nil\")\n\t}\n\tmySuggestions, found := searchResult.Suggest[tsName]\n\tif !found {\n\t\tt.Errorf(\"expected to find SearchResult.Suggest[%s]; got false\", tsName)\n\t}\n\tif mySuggestions == nil {\n\t\tt.Errorf(\"expected SearchResult.Suggest[%s] != nil; got nil\", tsName)\n\t}\n\n\tif len(mySuggestions) != 1 {\n\t\tt.Errorf(\"expected 1 suggestion; got %d\", len(mySuggestions))\n\t}\n\tmySuggestion := mySuggestions[0]\n\tif mySuggestion.Text != \"goolang\" {\n\t\tt.Errorf(\"expected Text = 'goolang'; got %s\", mySuggestion.Text)\n\t}\n\tif mySuggestion.Offset != 0 {\n\t\tt.Errorf(\"expected Offset = %d; got %d\", 0, mySuggestion.Offset)\n\t}\n\tif mySuggestion.Length != 7 {\n\t\tt.Errorf(\"expected Length = %d; got %d\", 7, mySuggestion.Length)\n\t}\n\tif len(mySuggestion.Options) != 1 {\n\t\tt.Errorf(\"expected 1 option; got %d\", len(mySuggestion.Options))\n\t}\n\tmyOption := mySuggestion.Options[0]\n\tif myOption.Text != \"golang\" {\n\t\tt.Errorf(\"expected Text = 'golang'; got %s\", myOption.Text)\n\t}\n\tif score := mySuggestion.Options[0].Score; score <= 0.0 {\n\t\tt.Errorf(\"expected options[0].Score > 0.0; got %v\", score)\n\t}\n}\n\nfunc TestPhraseSuggester(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) // AndLog(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\"}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\tphraseSuggesterName := \"my-suggestions\"\n\tps := NewPhraseSuggester(phraseSuggesterName)\n\tps = ps.Text(\"Goolang\")\n\tps = ps.Field(\"message\")\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tSuggester(ps).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Suggest == nil {\n\t\tt.Errorf(\"expected SearchResult.Suggest != nil; got nil\")\n\t}\n\tmySuggestions, found := searchResult.Suggest[phraseSuggesterName]\n\tif !found {\n\t\tt.Errorf(\"expected to find SearchResult.Suggest[%s]; got false\", phraseSuggesterName)\n\t}\n\tif mySuggestions == nil {\n\t\tt.Errorf(\"expected SearchResult.Suggest[%s] != nil; got nil\", phraseSuggesterName)\n\t}\n\n\tif len(mySuggestions) != 1 {\n\t\tt.Errorf(\"expected 1 suggestion; got %d\", len(mySuggestions))\n\t}\n\tmySuggestion := mySuggestions[0]\n\tif mySuggestion.Text != \"Goolang\" {\n\t\tt.Errorf(\"expected Text = 'Goolang'; got %s\", mySuggestion.Text)\n\t}\n\tif mySuggestion.Offset != 0 {\n\t\tt.Errorf(\"expected Offset = %d; got %d\", 0, mySuggestion.Offset)\n\t}\n\tif mySuggestion.Length != 7 {\n\t\tt.Errorf(\"expected Length = %d; got %d\", 7, mySuggestion.Length)\n\t}\n\tif want, have := 1, len(mySuggestion.Options); want != have {\n\t\tt.Errorf(\"expected len(options) = %d; got %d\", want, have)\n\t}\n\tif want, have := \"golang\", mySuggestion.Options[0].Text; want != have {\n\t\tt.Errorf(\"expected options[0].Text = %q; got %q\", want, have)\n\t}\n\tif score := mySuggestion.Options[0].Score; score <= 0.0 {\n\t\tt.Errorf(\"expected options[0].Score > 0.0; got %v\", score)\n\t}\n}\n\nfunc TestCompletionSuggester(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t) // AndLog(t)\n\n\ttweet1 := tweet{\n\t\tUser:    \"olivere\",\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tSuggest: NewSuggestField(\"Golang\", \"Elasticsearch\"),\n\t}\n\ttweet2 := tweet{\n\t\tUser:    \"olivere\",\n\t\tMessage: \"Another unrelated topic.\",\n\t\tSuggest: NewSuggestField(\"Another unrelated topic.\"),\n\t}\n\ttweet3 := tweet{\n\t\tUser:    \"sandrae\",\n\t\tMessage: \"Cycling is fun.\",\n\t\tSuggest: NewSuggestField(\"Cycling is fun.\"),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\tsuggesterName := \"my-suggestions\"\n\tcs := NewCompletionSuggester(suggesterName)\n\tcs = cs.Text(\"Golang\")\n\tcs = cs.Field(\"suggest_field\")\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tSuggester(cs).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Suggest == nil {\n\t\tt.Errorf(\"expected SearchResult.Suggest != nil; got nil\")\n\t}\n\tmySuggestions, found := searchResult.Suggest[suggesterName]\n\tif !found {\n\t\tt.Errorf(\"expected to find SearchResult.Suggest[%s]; got false\", suggesterName)\n\t}\n\tif mySuggestions == nil {\n\t\tt.Errorf(\"expected SearchResult.Suggest[%s] != nil; got nil\", suggesterName)\n\t}\n\n\tif len(mySuggestions) != 1 {\n\t\tt.Errorf(\"expected 1 suggestion; got %d\", len(mySuggestions))\n\t}\n\tmySuggestion := mySuggestions[0]\n\tif mySuggestion.Text != \"Golang\" {\n\t\tt.Errorf(\"expected Text = 'Golang'; got %s\", mySuggestion.Text)\n\t}\n\tif mySuggestion.Offset != 0 {\n\t\tt.Errorf(\"expected Offset = %d; got %d\", 0, mySuggestion.Offset)\n\t}\n\tif mySuggestion.Length != 6 {\n\t\tt.Errorf(\"expected Length = %d; got %d\", 7, mySuggestion.Length)\n\t}\n\tif len(mySuggestion.Options) != 1 {\n\t\tt.Errorf(\"expected 1 option; got %d\", len(mySuggestion.Options))\n\t}\n\tmyOption := mySuggestion.Options[0]\n\tif myOption.Text != \"Golang\" {\n\t\tt.Errorf(\"expected Text = 'Golang'; got %s\", myOption.Text)\n\t}\n\tif score := mySuggestion.Options[0].ScoreUnderscore; score <= 0.0 {\n\t\tt.Errorf(\"expected options[0].ScoreUnderscore > 0.0; got %v\", score)\n\t}\n}\n\nfunc TestContextSuggester(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// TODO make a nice way of creating tweets, as currently the context fields are unsupported as part of the suggestion fields\n\ttweet1 := `\n\t{\n\t\t\"user\":\"olivere\",\n\t\t\"message\":\"Welcome to Golang and Elasticsearch.\",\n\t\t\"retweets\":0,\n\t\t\"created\":\"0001-01-01T00:00:00Z\",\n\t\t\"suggest_field\":{\n\t\t\t\"input\":[\n\t\t\t\t\"Golang\",\n\t\t\t\t\"Elasticsearch\"\n\t\t\t],\n\t\t\t\"contexts\":{\n\t\t\t\t\"user_name\": [\"olivere\"]\n\t\t\t}\n\t\t}\n\t}\n\t`\n\ttweet2 := `\n\t{\n\t\t\"user\":\"sandrae\",\n\t\t\"message\":\"I like golfing\",\n\t\t\"retweets\":0,\n\t\t\"created\":\"0001-01-01T00:00:00Z\",\n\t\t\"suggest_field\":{\n\t\t\t\"input\":[\n\t\t\t\t\"Golfing\"\n\t\t\t],\n\t\t\t\"contexts\":{\n\t\t\t\t\"user_name\": [\"sandrae\"]\n\t\t\t}\n\t\t}\n\t}\n\t`\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName2).Id(\"1\").BodyString(tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName2).Id(\"2\").BodyString(tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tsuggesterName := \"my-suggestions\"\n\tcs := NewContextSuggester(suggesterName)\n\tcs = cs.Prefix(\"Gol\")\n\tcs = cs.Field(\"suggest_field\")\n\tcs = cs.ContextQueries(\n\t\tNewSuggesterCategoryQuery(\"user_name\", \"olivere\"),\n\t)\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName2).\n\t\tSuggester(cs).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Suggest == nil {\n\t\tt.Errorf(\"expected SearchResult.Suggest != nil; got nil\")\n\t}\n\tmySuggestions, found := searchResult.Suggest[suggesterName]\n\tif !found {\n\t\tt.Errorf(\"expected to find SearchResult.Suggest[%s]; got false\", suggesterName)\n\t}\n\tif mySuggestions == nil {\n\t\tt.Errorf(\"expected SearchResult.Suggest[%s] != nil; got nil\", suggesterName)\n\t}\n\n\t// sandra's tweet is not returned because of the user_name context\n\tif len(mySuggestions) != 1 {\n\t\tt.Errorf(\"expected 1 suggestion; got %d\", len(mySuggestions))\n\t}\n\tmySuggestion := mySuggestions[0]\n\tif mySuggestion.Text != \"Gol\" {\n\t\tt.Errorf(\"expected Text = 'Gol'; got %s\", mySuggestion.Text)\n\t}\n\tif mySuggestion.Offset != 0 {\n\t\tt.Errorf(\"expected Offset = %d; got %d\", 0, mySuggestion.Offset)\n\t}\n\tif mySuggestion.Length != 3 {\n\t\tt.Errorf(\"expected Length = %d; got %d\", 3, mySuggestion.Length)\n\t}\n\tif len(mySuggestion.Options) != 1 {\n\t\tt.Errorf(\"expected 1 option; got %d\", len(mySuggestion.Options))\n\t}\n\tmyOption := mySuggestion.Options[0]\n\tif myOption.Text != \"Golang\" {\n\t\tt.Errorf(\"expected Text = 'Golang'; got %s\", myOption.Text)\n\t}\n\tif myOption.Id != \"1\" {\n\t\tt.Errorf(\"expected Id = '1'; got %s\", myOption.Id)\n\t}\n\tif score := mySuggestion.Options[0].ScoreUnderscore; score <= 0.0 {\n\t\tt.Errorf(\"expected options[0].ScoreUnderscore > 0.0; got %v\", score)\n\t}\n}\n"
  },
  {
    "path": "search_terms_lookup.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// TermsLookup encapsulates the parameters needed to fetch terms.\n//\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-terms-query.html#query-dsl-terms-lookup.\ntype TermsLookup struct {\n\tindex   string\n\ttyp     string\n\tid      string\n\tpath    string\n\trouting string\n}\n\n// NewTermsLookup creates and initializes a new TermsLookup.\nfunc NewTermsLookup() *TermsLookup {\n\tt := &TermsLookup{}\n\treturn t\n}\n\n// Index name.\nfunc (t *TermsLookup) Index(index string) *TermsLookup {\n\tt.index = index\n\treturn t\n}\n\n// Type name.\n//\n// Deprecated: Types are in the process of being removed.\nfunc (t *TermsLookup) Type(typ string) *TermsLookup {\n\tt.typ = typ\n\treturn t\n}\n\n// Id to look up.\nfunc (t *TermsLookup) Id(id string) *TermsLookup {\n\tt.id = id\n\treturn t\n}\n\n// Path to use for lookup.\nfunc (t *TermsLookup) Path(path string) *TermsLookup {\n\tt.path = path\n\treturn t\n}\n\n// Routing value.\nfunc (t *TermsLookup) Routing(routing string) *TermsLookup {\n\tt.routing = routing\n\treturn t\n}\n\n// Source creates the JSON source of the builder.\nfunc (t *TermsLookup) Source() (interface{}, error) {\n\tsrc := make(map[string]interface{})\n\tif t.index != \"\" {\n\t\tsrc[\"index\"] = t.index\n\t}\n\tif t.typ != \"\" {\n\t\tsrc[\"type\"] = t.typ\n\t}\n\tif t.id != \"\" {\n\t\tsrc[\"id\"] = t.id\n\t}\n\tif t.path != \"\" {\n\t\tsrc[\"path\"] = t.path\n\t}\n\tif t.routing != \"\" {\n\t\tsrc[\"routing\"] = t.routing\n\t}\n\treturn src, nil\n}\n"
  },
  {
    "path": "search_terms_lookup_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestTermsLookup(t *testing.T) {\n\ttl := NewTermsLookup().Index(\"users\").Type(\"user\").Id(\"2\").Path(\"followers\")\n\tsrc, err := tl.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"id\":\"2\",\"index\":\"users\",\"path\":\"followers\",\"type\":\"user\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "search_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"reflect\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestSearchMatchAll(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tSize(100).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(3); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 3; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc TestSearchWithCustomHTTPHeaders(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tres, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tSize(100).\n\t\tPretty(true).\n\t\tHeaders(http.Header{\n\t\t\t\"X-ID\":      []string{\"A\", \"B\"},\n\t\t\t\"Custom-ID\": []string{\"olivere\"},\n\t\t}).\n\t\tHeader(\"X-ID\", \"12345\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif got, want := res.TotalHits(), int64(3); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := res.Header.Get(\"Content-Type\"), \"application/json; charset=UTF-8\"; got != want {\n\t\tt.Errorf(\"expected SearchResult.Header(%q) = %q; got %q\", \"Content-Type\", want, got)\n\t}\n}\n\nfunc TestSearchMatchAllWithRequestCacheDisabled(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents, with request cache disabled\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tSize(100).\n\t\tPretty(true).\n\t\tRequestCache(false).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(3); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 3; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n}\n\nfunc TestSearchTotalHits(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\tcount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif count == 0 {\n\t\tt.Fatalf(\"expected more than %d documents\", count)\n\t}\n\n\t// RestTotalHitsAsInt(false) (default)\n\t{\n\t\tres, err := client.Search().Index(testIndexName).Query(NewMatchAllQuery()).RestTotalHitsAsInt(false).Pretty(true).Do(context.TODO())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res == nil {\n\t\t\tt.Fatal(\"expected SearchResult != nil; got nil\")\n\t\t}\n\t\tif want, have := count, res.TotalHits(); want != have {\n\t\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, have)\n\t\t}\n\t\tif res.Hits == nil || res.Hits.TotalHits == nil {\n\t\t\tt.Fatal(\"expected SearchResult.Hits._ != nil; got nil\")\n\t\t}\n\t\tif want, have := count, res.Hits.TotalHits.Value; want != have {\n\t\t\tt.Errorf(\"expected SearchResult.TotalHits.Value = %d; got %d\", want, have)\n\t\t}\n\t\tif want, have := \"eq\", res.Hits.TotalHits.Relation; want != have {\n\t\t\tt.Errorf(\"expected SearchResult.TotalHits.Relation = %q; got %q\", want, have)\n\t\t}\n\t}\n\n\t// RestTotalHitsAsInt(true)\n\t{\n\t\tres, err := client.Search().Index(testIndexName).Query(NewMatchAllQuery()).RestTotalHitsAsInt(true).Pretty(true).Do(context.TODO())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif res == nil {\n\t\t\tt.Fatal(\"expected SearchResult != nil; got nil\")\n\t\t}\n\t\tif want, have := count, res.TotalHits(); want != have {\n\t\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, have)\n\t\t}\n\t\tif res.Hits == nil || res.Hits.TotalHits == nil {\n\t\t\tt.Fatal(\"expected SearchResult.Hits._ != nil; got nil\")\n\t\t}\n\t\tif want, have := count, res.Hits.TotalHits.Value; want != have {\n\t\t\tt.Errorf(\"expected SearchResult.TotalHits.Value = %d; got %d\", want, have)\n\t\t}\n\t\tif want, have := \"eq\", res.Hits.TotalHits.Relation; want != have {\n\t\t\tt.Errorf(\"expected SearchResult.TotalHits.Relation = %q; got %q\", want, have)\n\t\t}\n\t}\n}\n\nfunc BenchmarkSearchMatchAll(b *testing.B) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(b)\n\n\tfor n := 0; n < b.N; n++ {\n\t\t// Match all should return all documents\n\t\tall := NewMatchAllQuery()\n\t\tsearchResult, err := client.Search().Index(testIndexName).Query(all).Do(context.TODO())\n\t\tif err != nil {\n\t\t\tb.Fatal(err)\n\t\t}\n\t\tif searchResult.Hits == nil {\n\t\t\tb.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t\t}\n\t\tif searchResult.TotalHits() == 0 {\n\t\t\tb.Errorf(\"expected SearchResult.TotalHits() > %d; got %d\", 0, searchResult.TotalHits())\n\t\t}\n\t}\n}\n\nfunc TestSearchResultTotalHits(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\tcount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tall := NewMatchAllQuery()\n\tsearchResult, err := client.Search().Index(testIndexName).Query(all).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tgot := searchResult.TotalHits()\n\tif got != count {\n\t\tt.Fatalf(\"expected %d hits; got: %d\", count, got)\n\t}\n\n\t// No hits\n\tsearchResult = &SearchResult{}\n\tgot = searchResult.TotalHits()\n\tif got != 0 {\n\t\tt.Errorf(\"expected %d hits; got: %d\", 0, got)\n\t}\n}\n\nfunc TestSearchResultWithProfiling(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tall := NewMatchAllQuery()\n\tsearchResult, err := client.Search().Index(testIndexName).Query(all).Profile(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif searchResult.Profile == nil {\n\t\tt.Fatal(\"Profiled MatchAll query did not return profiling data with results\")\n\t}\n}\n\nfunc TestSearchResultEach(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\tall := NewMatchAllQuery()\n\tsearchResult, err := client.Search().Index(testIndexName).Query(all).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Iterate over non-ptr type\n\tvar aTweet tweet\n\tcount := 0\n\tfor _, item := range searchResult.Each(reflect.TypeOf(aTweet)) {\n\t\tcount++\n\t\t_, ok := item.(tweet)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected hit to be serialized as tweet; got: %v\", reflect.ValueOf(item))\n\t\t}\n\t}\n\tif count == 0 {\n\t\tt.Errorf(\"expected to find some hits; got: %d\", count)\n\t}\n\n\t// Iterate over ptr-type\n\tcount = 0\n\tvar aTweetPtr *tweet\n\tfor _, item := range searchResult.Each(reflect.TypeOf(aTweetPtr)) {\n\t\tcount++\n\t\ttw, ok := item.(*tweet)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected hit to be serialized as tweet; got: %v\", reflect.ValueOf(item))\n\t\t}\n\t\tif tw == nil {\n\t\t\tt.Fatal(\"expected hit to not be nil\")\n\t\t}\n\t}\n\tif count == 0 {\n\t\tt.Errorf(\"expected to find some hits; got: %d\", count)\n\t}\n\n\t// Does not iterate when no hits are found\n\tsearchResult = &SearchResult{Hits: nil}\n\tcount = 0\n\tfor _, item := range searchResult.Each(reflect.TypeOf(aTweet)) {\n\t\tcount++\n\t\t_ = item\n\t}\n\tif count != 0 {\n\t\tt.Errorf(\"expected to not find any hits; got: %d\", count)\n\t}\n\tsearchResult = &SearchResult{Hits: &SearchHits{Hits: make([]*SearchHit, 0)}}\n\tcount = 0\n\tfor _, item := range searchResult.Each(reflect.TypeOf(aTweet)) {\n\t\tcount++\n\t\t_ = item\n\t}\n\tif count != 0 {\n\t\tt.Errorf(\"expected to not find any hits; got: %d\", count)\n\t}\n}\n\nfunc TestSearchResultEachNoSource(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocsNoSource(t)\n\n\tall := NewMatchAllQuery()\n\tsearchResult, err := client.Search().Index(testNoSourceIndexName).Query(all).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Iterate over non-ptr type\n\tvar aTweet tweet\n\tcount := 0\n\tfor _, item := range searchResult.Each(reflect.TypeOf(aTweet)) {\n\t\tcount++\n\t\ttw, ok := item.(tweet)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected hit to be serialized as tweet; got: %v\", reflect.ValueOf(item))\n\t\t}\n\n\t\tif tw.User != \"\" {\n\t\t\tt.Fatalf(\"expected no _source hit to be empty tweet; got: %v\", reflect.ValueOf(item))\n\t\t}\n\t}\n\tif count != 2 {\n\t\tt.Errorf(\"expected to find 2 hits; got: %d\", count)\n\t}\n\n\t// Iterate over ptr-type\n\tcount = 0\n\tvar aTweetPtr *tweet\n\tfor _, item := range searchResult.Each(reflect.TypeOf(aTweetPtr)) {\n\t\tcount++\n\t\ttw, ok := item.(*tweet)\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected hit to be serialized as tweet; got: %v\", reflect.ValueOf(item))\n\t\t}\n\t\tif tw != nil {\n\t\t\tt.Fatal(\"expected hit to be nil\")\n\t\t}\n\t}\n\tif count != 2 {\n\t\tt.Errorf(\"expected to find 2 hits; got: %d\", count)\n\t}\n}\n\nfunc TestSearchSorting(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser: \"olivere\", Retweets: 108,\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tCreated: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser: \"olivere\", Retweets: 0,\n\t\tMessage: \"Another unrelated topic.\",\n\t\tCreated: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser: \"sandrae\", Retweets: 12,\n\t\tMessage: \"Cycling is fun.\",\n\t\tCreated: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\tall := NewMatchAllQuery()\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(all).\n\t\tSort(\"created\", false).\n\t\tTimeout(\"1s\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 3 {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 3, len(searchResult.Hits.Hits))\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc TestSearchSortingBySorters(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser: \"olivere\", Retweets: 108,\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tCreated: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser: \"olivere\", Retweets: 0,\n\t\tMessage: \"Another unrelated topic.\",\n\t\tCreated: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser: \"sandrae\", Retweets: 12,\n\t\tMessage: \"Cycling is fun.\",\n\t\tCreated: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\tall := NewMatchAllQuery()\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(all).\n\t\tSortBy(NewFieldSort(\"created\").Desc(), NewScoreSort()).\n\t\tTimeout(\"1s\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 3 {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 3, len(searchResult.Hits.Hits))\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc TestSearchSpecificFields(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Retweets: 1, Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Retweets: 2, Message: \"Another unrelated topic.\"}\n\ttweet3 := tweet{User: \"sandrae\", Retweets: 3, Message: \"Cycling is fun.\"}\n\ttweets := []tweet{\n\t\ttweet1,\n\t\ttweet2,\n\t\ttweet3,\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\tall := NewMatchAllQuery()\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(all).\n\t\tStoredFields(\"message\").\n\t\tDocvalueFields(\"retweets\").\n\t\tSort(\"created\", true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 3 {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 3, len(searchResult.Hits.Hits))\n\t}\n\n\t// Manually inspect the fields\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\tif hit.Source != nil {\n\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Source to be nil; got: %v\", hit.Source)\n\t\t}\n\t\tif hit.Fields == nil {\n\t\t\tt.Fatal(\"expected SearchResult.Hits.Hit.Fields to be != nil\")\n\t\t}\n\t\tfield, found := hit.Fields[\"message\"]\n\t\tif !found {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Fields[%s] to be found\", \"message\")\n\t\t}\n\t\tfields, ok := field.([]interface{})\n\t\tif !ok {\n\t\t\tt.Errorf(\"expected []interface{}; got: %v\", reflect.TypeOf(fields))\n\t\t}\n\t\tif len(fields) != 1 {\n\t\t\tt.Errorf(\"expected a field with 1 entry; got: %d\", len(fields))\n\t\t}\n\t\tmessage, ok := fields[0].(string)\n\t\tif !ok {\n\t\t\tt.Errorf(\"expected a string; got: %v\", reflect.TypeOf(fields[0]))\n\t\t}\n\t\tif message == \"\" {\n\t\t\tt.Errorf(\"expected a message; got: %q\", message)\n\t\t}\n\t}\n\n\t// With the new helper method for fields\n\tfor i, hit := range searchResult.Hits.Hits {\n\t\t// Field: message\n\t\titems, ok := hit.Fields.Strings(\"message\")\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Fields[%s] to be found\", \"message\")\n\t\t}\n\t\tif want, have := 1, len(items); want != have {\n\t\t\tt.Fatalf(\"expected a field with %d entries; got %d\", want, have)\n\t\t}\n\t\tif want, have := tweets[i].Message, items[0]; want != have {\n\t\t\tt.Fatalf(\"expected message[%d]=%q; got %q\", i, want, have)\n\t\t}\n\n\t\t// Field: retweets\n\t\tretweets, ok := hit.Fields.Float64s(\"retweets\")\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Fields[%s] to be found\", \"retweets\")\n\t\t}\n\t\tif want, have := 1, len(retweets); want != have {\n\t\t\tt.Fatalf(\"expected a field with %d entries; got %d\", want, have)\n\t\t}\n\t\tif want, have := tweets[i].Retweets, int(retweets[0]); want != have {\n\t\t\tt.Fatalf(\"expected retweets[%d]=%q; got %q\", i, want, have)\n\t\t}\n\n\t\t// Field should not exist\n\t\tnumbers, ok := hit.Fields.Float64s(\"score\")\n\t\tif ok {\n\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Fields[%s] to NOT be found\", \"numbers\")\n\t\t}\n\t\tif numbers != nil {\n\t\t\tt.Fatalf(\"expected no field %q; got %+v\", \"numbers\", numbers)\n\t\t}\n\t}\n}\n\nfunc TestSearchExplain(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser: \"olivere\", Retweets: 108,\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tCreated: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser: \"olivere\", Retweets: 0,\n\t\tMessage: \"Another unrelated topic.\",\n\t\tCreated: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser: \"sandrae\", Retweets: 12,\n\t\tMessage: \"Cycling is fun.\",\n\t\tCreated: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Match all should return all documents\n\tall := NewMatchAllQuery()\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(all).\n\t\tExplain(true).\n\t\tTimeout(\"1s\").\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 3 {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 3, len(searchResult.Hits.Hits))\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\tif hit.Explanation == nil {\n\t\t\tt.Fatal(\"expected search explanation\")\n\t\t}\n\t\tif hit.Explanation.Value <= 0.0 {\n\t\t\tt.Errorf(\"expected explanation value to be > 0.0; got: %v\", hit.Explanation.Value)\n\t\t}\n\t\tif hit.Explanation.Description == \"\" {\n\t\t\tt.Errorf(\"expected explanation description != %q; got: %q\", \"\", hit.Explanation.Description)\n\t\t}\n\t}\n}\n\nfunc TestSearchSource(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser: \"olivere\", Retweets: 108,\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tCreated: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser: \"olivere\", Retweets: 0,\n\t\tMessage: \"Another unrelated topic.\",\n\t\tCreated: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser: \"sandrae\", Retweets: 12,\n\t\tMessage: \"Cycling is fun.\",\n\t\tCreated: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Set up the request JSON manually to pass to the search service via Source()\n\tsource := map[string]interface{}{\n\t\t\"query\": map[string]interface{}{\n\t\t\t\"match_all\": map[string]interface{}{},\n\t\t},\n\t}\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tSource(source). // sets the JSON request\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult.TotalHits())\n\t}\n}\n\nfunc TestSearchSourceWithString(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser: \"olivere\", Retweets: 108,\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tCreated: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser: \"olivere\", Retweets: 0,\n\t\tMessage: \"Another unrelated topic.\",\n\t\tCreated: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser: \"sandrae\", Retweets: 12,\n\t\tMessage: \"Cycling is fun.\",\n\t\tCreated: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tSource(`{\"query\":{\"match_all\":{}}}`). // sets the JSON request\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult.TotalHits())\n\t}\n}\n\nfunc TestSearchRawString(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser: \"olivere\", Retweets: 108,\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tCreated: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser: \"olivere\", Retweets: 0,\n\t\tMessage: \"Another unrelated topic.\",\n\t\tCreated: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser: \"sandrae\", Retweets: 12,\n\t\tMessage: \"Cycling is fun.\",\n\t\tCreated: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tquery := RawStringQuery(`{\"match_all\":{}}`)\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(query).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult.TotalHits())\n\t}\n}\n\nfunc TestSearchSearchSource(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser: \"olivere\", Retweets: 108,\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tCreated: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser: \"olivere\", Retweets: 0,\n\t\tMessage: \"Another unrelated topic.\",\n\t\tCreated: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser: \"sandrae\", Retweets: 12,\n\t\tMessage: \"Cycling is fun.\",\n\t\tCreated: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Set up the search source manually and pass it to the search service via SearchSource()\n\tss := NewSearchSource().\n\t\tQuery(NewMatchAllQuery()).\n\t\tIndexBoost(testIndexName, 1.0).\n\t\tIndexBoosts(IndexBoost{Index: testIndexName2, Boost: 2.0}).\n\t\tFrom(0).Size(2)\n\n\t// One can use ss.Source() to get to the raw interface{} that will be used\n\t// as the search request JSON by the SearchService.\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tSearchSource(ss). // sets the SearchSource\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 2 {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 2, len(searchResult.Hits.Hits))\n\t}\n}\n\nfunc TestSearchInnerHitsOnHasChild(t *testing.T) {\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tctx := context.Background()\n\n\t// Create join index\n\tcreateIndex, err := client.CreateIndex(testJoinIndex).Body(testJoinMapping).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndex)\n\t}\n\n\t// Add documents\n\t// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/parent-join.html for example code.\n\tdoc1 := joinDoc{\n\t\tMessage:   \"This is a question\",\n\t\tJoinField: &joinField{Name: \"question\"},\n\t}\n\t_, err = client.Index().Index(testJoinIndex).Id(\"1\").BodyJson(&doc1).Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdoc2 := joinDoc{\n\t\tMessage:   \"This is another question\",\n\t\tJoinField: \"question\",\n\t}\n\t_, err = client.Index().Index(testJoinIndex).Id(\"2\").BodyJson(&doc2).Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdoc3 := joinDoc{\n\t\tMessage: \"This is an answer\",\n\t\tJoinField: &joinField{\n\t\t\tName:   \"answer\",\n\t\t\tParent: \"1\",\n\t\t},\n\t}\n\t_, err = client.Index().Index(testJoinIndex).Id(\"3\").BodyJson(&doc3).Routing(\"1\").Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdoc4 := joinDoc{\n\t\tMessage: \"This is another answer\",\n\t\tJoinField: &joinField{\n\t\t\tName:   \"answer\",\n\t\t\tParent: \"1\",\n\t\t},\n\t}\n\t_, err = client.Index().Index(testJoinIndex).Id(\"4\").BodyJson(&doc4).Routing(\"1\").Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testJoinIndex).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Search for all documents that have an answer, and return those answers as inner hits\n\tbq := NewBoolQuery()\n\tbq = bq.Must(NewMatchAllQuery())\n\tbq = bq.Filter(NewHasChildQuery(\"answer\", NewMatchAllQuery()).\n\t\tInnerHit(NewInnerHit().Name(\"answers\")))\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testJoinIndex).\n\t\tQuery(bq).\n\t\tPretty(true).\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 1 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 2, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 1 {\n\t\tt.Fatalf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 2, len(searchResult.Hits.Hits))\n\t}\n\n\thit := searchResult.Hits.Hits[0]\n\tif want, have := \"1\", hit.Id; want != have {\n\t\tt.Fatalf(\"expected tweet %q; got: %q\", want, have)\n\t}\n\tif hit.InnerHits == nil {\n\t\tt.Fatalf(\"expected inner hits; got: %v\", hit.InnerHits)\n\t}\n\tif want, have := 1, len(hit.InnerHits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tinnerHits, found := hit.InnerHits[\"answers\"]\n\tif !found {\n\t\tt.Fatalf(\"expected inner hits for name %q\", \"answers\")\n\t}\n\tif innerHits == nil || innerHits.Hits == nil {\n\t\tt.Fatal(\"expected inner hits != nil\")\n\t}\n\tif want, have := 2, len(innerHits.Hits.Hits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tif want, have := \"3\", innerHits.Hits.Hits[0].Id; want != have {\n\t\tt.Fatalf(\"expected inner hit with id %q; got: %q\", want, have)\n\t}\n\tif want, have := \"4\", innerHits.Hits.Hits[1].Id; want != have {\n\t\tt.Fatalf(\"expected inner hit with id %q; got: %q\", want, have)\n\t}\n}\n\nfunc TestSearchInnerHitsOnHasParent(t *testing.T) {\n\t// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tctx := context.Background()\n\n\t// Create join index\n\tcreateIndex, err := client.CreateIndex(testJoinIndex).Body(testJoinMapping).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndex)\n\t}\n\n\t// Add documents\n\t// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/parent-join.html for example code.\n\tdoc1 := joinDoc{\n\t\tMessage:   \"This is a question\",\n\t\tJoinField: &joinField{Name: \"question\"},\n\t}\n\t_, err = client.Index().Index(testJoinIndex).Id(\"1\").BodyJson(&doc1).Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdoc2 := joinDoc{\n\t\tMessage:   \"This is another question\",\n\t\tJoinField: \"question\",\n\t}\n\t_, err = client.Index().Index(testJoinIndex).Id(\"2\").BodyJson(&doc2).Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdoc3 := joinDoc{\n\t\tMessage: \"This is an answer\",\n\t\tJoinField: &joinField{\n\t\t\tName:   \"answer\",\n\t\t\tParent: \"1\",\n\t\t},\n\t}\n\t_, err = client.Index().Index(testJoinIndex).Id(\"3\").BodyJson(&doc3).Routing(\"1\").Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdoc4 := joinDoc{\n\t\tMessage: \"This is another answer\",\n\t\tJoinField: &joinField{\n\t\t\tName:   \"answer\",\n\t\t\tParent: \"1\",\n\t\t},\n\t}\n\t_, err = client.Index().Index(testJoinIndex).Id(\"4\").BodyJson(&doc4).Routing(\"1\").Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testJoinIndex).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Search for all documents that have an answer, and return those answers as inner hits\n\tbq := NewBoolQuery()\n\tbq = bq.Must(NewMatchAllQuery())\n\tbq = bq.Filter(NewHasParentQuery(\"question\", NewMatchAllQuery()).\n\t\tInnerHit(NewInnerHit().Name(\"answers\")))\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testJoinIndex).\n\t\tQuery(bq).\n\t\tPretty(true).\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif want, have := int64(2), searchResult.TotalHits(); want != have {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, have)\n\t}\n\tif want, have := 2, len(searchResult.Hits.Hits); want != have {\n\t\tt.Fatalf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, have)\n\t}\n\n\thit := searchResult.Hits.Hits[0]\n\tif want, have := \"3\", hit.Id; want != have {\n\t\tt.Fatalf(\"expected tweet %q; got: %q\", want, have)\n\t}\n\tif hit.InnerHits == nil {\n\t\tt.Fatalf(\"expected inner hits; got: %v\", hit.InnerHits)\n\t}\n\tif want, have := 1, len(hit.InnerHits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tinnerHits, found := hit.InnerHits[\"answers\"]\n\tif !found {\n\t\tt.Fatalf(\"expected inner hits for name %q\", \"tweets\")\n\t}\n\tif innerHits == nil || innerHits.Hits == nil {\n\t\tt.Fatal(\"expected inner hits != nil\")\n\t}\n\tif want, have := 1, len(innerHits.Hits.Hits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tif want, have := \"1\", innerHits.Hits.Hits[0].Id; want != have {\n\t\tt.Fatalf(\"expected inner hit with id %q; got: %q\", want, have)\n\t}\n\n\thit = searchResult.Hits.Hits[1]\n\tif want, have := \"4\", hit.Id; want != have {\n\t\tt.Fatalf(\"expected tweet %q; got: %q\", want, have)\n\t}\n\tif hit.InnerHits == nil {\n\t\tt.Fatalf(\"expected inner hits; got: %v\", hit.InnerHits)\n\t}\n\tif want, have := 1, len(hit.InnerHits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tinnerHits, found = hit.InnerHits[\"answers\"]\n\tif !found {\n\t\tt.Fatalf(\"expected inner hits for name %q\", \"tweets\")\n\t}\n\tif innerHits == nil || innerHits.Hits == nil {\n\t\tt.Fatal(\"expected inner hits != nil\")\n\t}\n\tif want, have := 1, len(innerHits.Hits.Hits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tif want, have := \"1\", innerHits.Hits.Hits[0].Id; want != have {\n\t\tt.Fatalf(\"expected inner hit with id %q; got: %q\", want, have)\n\t}\n}\n\nfunc TestSearchInnerHitsOnNested(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndLog(t)\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tctx := context.Background()\n\n\t// Create index\n\tcreateIndex, err := client.CreateIndex(testIndexName5).Body(`{\n\t\t\"settings\":{\n\t\t\t\"number_of_shards\":1,\n\t\t\t\"number_of_replicas\":0\n\t\t},\n\t\t\"mappings\": {\n\t\t\t\"properties\": {\n\t\t\t  \t\"comments\": {\n\t\t\t\t\t\"type\": \"nested\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}`).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndex)\n\t}\n\n\t// Add documents\n\t// See https://www.elastic.co/guide/en/elasticsearch/reference/7.9/inner-hits.html#nested-inner-hits for example code.\n\ttype comment struct {\n\t\tAuthor string `json:\"author\"`\n\t\tNumber int    `json:\"number\"`\n\t}\n\ttype doc struct {\n\t\tTitle    string    `json:\"title\"`\n\t\tComments []comment `json:\"comments\"`\n\t}\n\tdoc1 := doc{\n\t\tTitle: \"Test title\",\n\t\tComments: []comment{\n\t\t\t{Author: \"kimchy\", Number: 1},\n\t\t\t{Author: \"nik9000\", Number: 2},\n\t\t},\n\t}\n\t_, err = client.Index().Index(testIndexName5).Id(\"1\").BodyJson(&doc1).Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Search for all documents that have an answer, and return those answers as inner hits\n\tq := NewNestedQuery(\"comments\", NewMatchQuery(\"comments.number\", 2)).InnerHit(NewInnerHit())\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName5).\n\t\tQuery(q).\n\t\tPretty(true).\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 1 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 2, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 1 {\n\t\tt.Fatalf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 2, len(searchResult.Hits.Hits))\n\t}\n\n\thit := searchResult.Hits.Hits[0]\n\tif want, have := \"1\", hit.Id; want != have {\n\t\tt.Fatalf(\"expected tweet %q; got: %q\", want, have)\n\t}\n\tif hit.InnerHits == nil {\n\t\tt.Fatalf(\"expected inner hits; got: %v\", hit.InnerHits)\n\t}\n\tif want, have := 1, len(hit.InnerHits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tinnerHits, found := hit.InnerHits[\"comments\"]\n\tif !found {\n\t\tt.Fatalf(\"expected inner hits for name %q\", \"comments\")\n\t}\n\tif innerHits == nil || innerHits.Hits == nil {\n\t\tt.Fatal(\"expected inner hits != nil\")\n\t}\n\tif want, have := 1, len(innerHits.Hits.Hits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tif want, have := \"1\", innerHits.Hits.Hits[0].Id; want != have {\n\t\tt.Fatalf(\"expected inner hit with id %q; got: %q\", want, have)\n\t}\n}\n\nfunc TestSearchInnerHitsOnNestedHierarchy(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t)\n\tclient := setupTestClientAndCreateIndex(t)\n\n\tctx := context.Background()\n\n\t// Create index\n\tcreateIndex, err := client.CreateIndex(testIndexName5).Body(`{\n\t\t\"settings\":{\n\t\t\t\"number_of_shards\":1,\n\t\t\t\"number_of_replicas\":0\n\t\t},\n\t\t\"mappings\": {\n\t\t\t\"properties\": {\n\t\t\t  \t\"comments\": {\n\t\t\t\t\t\"type\": \"nested\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t  \t\t\"votes\": {\n\t\t\t\t\t\t\t\"type\": \"nested\"\n\t\t\t\t  \t\t}\n\t\t\t\t\t}\n\t\t\t  \t}\n\t\t\t}\n\t\t}\n\t}`).Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndex)\n\t}\n\n\t// Add documents\n\t// See https://www.elastic.co/guide/en/elasticsearch/reference/7.9/inner-hits.html#hierarchical-nested-inner-hits for example code.\n\ttype vote struct {\n\t\tVoter string `json:\"voter\"`\n\t\tValue int    `json:\"value\"`\n\t}\n\ttype comment struct {\n\t\tAuthor string `json:\"author\"`\n\t\tText   string `json:\"text\"`\n\t\tVotes  []vote `json:\"votes\"`\n\t}\n\ttype doc struct {\n\t\tTitle    string    `json:\"title\"`\n\t\tComments []comment `json:\"comments\"`\n\t}\n\tdoc1 := doc{\n\t\tTitle: \"Test title\",\n\t\tComments: []comment{\n\t\t\t{Author: \"kimchy\", Text: \"words words words\", Votes: []vote{}},\n\t\t\t{Author: \"nik9000\", Text: \"words words words\", Votes: []vote{{Voter: \"kimchy\", Value: 1}, {Voter: \"other\", Value: -1}}},\n\t\t},\n\t}\n\t_, err = client.Index().Index(testIndexName5).Id(\"1\").BodyJson(&doc1).Refresh(\"true\").Do(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Search for all documents that have an answer, and return those answers as inner hits\n\tq := NewNestedQuery(\"comments.votes\", NewMatchQuery(\"comments.votes.voter\", \"kimchy\")).InnerHit(NewInnerHit())\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName5).\n\t\tQuery(q).\n\t\tPretty(true).\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 1 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 2, searchResult.TotalHits())\n\t}\n\tif len(searchResult.Hits.Hits) != 1 {\n\t\tt.Fatalf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", 2, len(searchResult.Hits.Hits))\n\t}\n\n\thit := searchResult.Hits.Hits[0]\n\tif want, have := \"1\", hit.Id; want != have {\n\t\tt.Fatalf(\"expected tweet %q; got: %q\", want, have)\n\t}\n\tif hit.InnerHits == nil {\n\t\tt.Fatalf(\"expected inner hits; got: %v\", hit.InnerHits)\n\t}\n\tif want, have := 1, len(hit.InnerHits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tinnerHits, found := hit.InnerHits[\"comments.votes\"]\n\tif !found {\n\t\tt.Fatalf(\"expected inner hits for name %q\", \"comments.votes\")\n\t}\n\tif innerHits == nil || innerHits.Hits == nil {\n\t\tt.Fatal(\"expected inner hits != nil\")\n\t}\n\tif want, have := 1, len(innerHits.Hits.Hits); want != have {\n\t\tt.Fatalf(\"expected %d inner hits; got: %d\", want, have)\n\t}\n\tif want, have := \"1\", innerHits.Hits.Hits[0].Id; want != have {\n\t\tt.Fatalf(\"expected inner hit with id %q; got: %q\", want, have)\n\t}\n}\n\nfunc TestSearchBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndices  []string\n\t\tTypes    []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"/_search\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{},\n\t\t\t\"/index1/_search\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{},\n\t\t\t\"/index1%2Cindex2/_search\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"type1\"},\n\t\t\t\"/_all/type1/_search\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{\"type1\"},\n\t\t\t\"/index1/type1/_search\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{\"type1\", \"type2\"},\n\t\t\t\"/index1%2Cindex2/type1%2Ctype2/_search\",\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"type1\", \"type2\"},\n\t\t\t\"/_all/type1%2Ctype2/_search\",\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tpath, _, err := client.Search().Index(test.Indices...).Type(test.Types...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestSearchFilterPath(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tall := NewMatchAllQuery()\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(all).\n\t\tFilterPath(\n\t\t\t\"took\",\n\t\t\t\"hits.hits._id\",\n\t\t\t\"hits.hits._source.user\",\n\t\t\t\"hits.hits._source.message\",\n\t\t).\n\t\tTimeout(\"1s\").\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Fatalf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\t// 0 because it was filtered out\n\tif want, got := int64(0), searchResult.TotalHits(); want != got {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif want, got := 3, len(searchResult.Hits.Hits); want != got {\n\t\tt.Fatalf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif want, got := \"\", hit.Index; want != got {\n\t\t\tt.Fatalf(\"expected index %q, got %q\", want, got)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\t// user field\n\t\tv, found := item[\"user\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit[%q] to be found\", \"user\")\n\t\t}\n\t\tif v == \"\" {\n\t\t\tt.Fatalf(\"expected user field, got %v (%T)\", v, v)\n\t\t}\n\t\t// No retweets field\n\t\tv, found = item[\"retweets\"]\n\t\tif found {\n\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit[%q] to not be found, got %v\", \"retweets\", v)\n\t\t}\n\t\tif v == \"\" {\n\t\t\tt.Fatalf(\"expected user field, got %v (%T)\", v, v)\n\t\t}\n\t}\n}\n\nfunc TestSearchAfter(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{\n\t\tUser: \"olivere\", Retweets: 108,\n\t\tMessage: \"Welcome to Golang and Elasticsearch.\",\n\t\tCreated: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC),\n\t}\n\ttweet2 := tweet{\n\t\tUser: \"olivere\", Retweets: 0,\n\t\tMessage: \"Another unrelated topic.\",\n\t\tCreated: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC),\n\t}\n\ttweet3 := tweet{\n\t\tUser: \"sandrae\", Retweets: 12,\n\t\tMessage: \"Cycling is fun.\",\n\t\tCreated: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC),\n\t}\n\n\t// Add all documents\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t_, err = client.Refresh().Index(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tSearchAfter(\"olivere\").\n\t\tSort(\"user\", true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif searchResult.TotalHits() != 3 {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", 3, searchResult.TotalHits())\n\t}\n\tif want, got := 1, len(searchResult.Hits.Hits); want != got {\n\t\tt.Fatalf(\"expected len(SearchResult.Hits.Hits) = %d; got: %d\", want, got)\n\t}\n\thit := searchResult.Hits.Hits[0]\n\tif want, got := \"3\", hit.Id; want != got {\n\t\tt.Fatalf(\"expected tweet %q; got: %q\", want, got)\n\t}\n}\n\nfunc TestSearchResultWithFieldCollapsing(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tCollapse(NewCollapseBuilder(\"user\")).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif searchResult.Hits == nil {\n\t\tt.Fatalf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got := searchResult.TotalHits(); got == 0 {\n\t\tt.Fatalf(\"expected SearchResult.TotalHits() > 0; got %d\", got)\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif len(hit.Fields) == 0 {\n\t\t\tt.Fatal(\"expected fields in SearchResult\")\n\t\t}\n\t\tusersVal, ok := hit.Fields[\"user\"]\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected %q field in fields of SearchResult\", \"user\")\n\t\t}\n\t\tusers, ok := usersVal.([]interface{})\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected slice of strings in field of SearchResult, got %T\", usersVal)\n\t\t}\n\t\tif len(users) != 1 {\n\t\t\tt.Fatalf(\"expected 1 entry in users slice, got %d\", len(users))\n\t\t}\n\t}\n}\n\nfunc TestSearchResultWithFieldCollapsingAndInnerHits(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tCollapse(\n\t\t\tNewCollapseBuilder(\"user\").\n\t\t\t\tInnerHit(\n\t\t\t\t\tNewInnerHit().Name(\"last_tweets\").Size(5).Sort(\"created\", true),\n\t\t\t\t).\n\t\t\t\tMaxConcurrentGroupRequests(4)).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif searchResult.Hits == nil {\n\t\tt.Fatalf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got := searchResult.TotalHits(); got == 0 {\n\t\tt.Fatalf(\"expected SearchResult.TotalHits() > 0; got %d\", got)\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Fatalf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif len(hit.Fields) == 0 {\n\t\t\tt.Fatal(\"expected fields in SearchResult\")\n\t\t}\n\t\tusersVal, ok := hit.Fields[\"user\"]\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected %q field in fields of SearchResult\", \"user\")\n\t\t}\n\t\tusers, ok := usersVal.([]interface{})\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected slice of strings in field of SearchResult, got %T\", usersVal)\n\t\t}\n\t\tif len(users) != 1 {\n\t\t\tt.Fatalf(\"expected 1 entry in users slice, got %d\", len(users))\n\t\t}\n\t\tlastTweets, ok := hit.InnerHits[\"last_tweets\"]\n\t\tif !ok {\n\t\t\tt.Fatalf(\"expected inner_hits named %q in SearchResult\", \"last_tweets\")\n\t\t}\n\t\tif lastTweets == nil {\n\t\t\tt.Fatal(\"expected inner_hits in SearchResult\")\n\t\t}\n\t}\n}\n\nfunc TestSearchScriptQuery(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// ES uses Painless as default scripting engine in 6.x\n\t// Another example of using painless would be:\n\t//\n\t//\tscript := NewScript(`\n\t//\tString username = doc['user'].value;\n\t//\treturn username == 'olivere'\n\t//`)\n\t// See https://www.elastic.co/guide/en/elasticsearch/painless/6.7/painless-examples.html\n\tscript := NewScript(\"doc['user'].value == 'olivere'\")\n\tquery := NewScriptQuery(script)\n\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(query).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif want, have := int64(2), searchResult.TotalHits(); want != have {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, have)\n\t}\n\tif want, have := 2, len(searchResult.Hits.Hits); want != have {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, have)\n\t}\n}\n\nfunc TestSearchWithDocvalueFields(t *testing.T) {\n\t// client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\n\t// Match all should return all documents\n\tsearchResult, err := client.Search().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tDocvalueFields(\"user\", \"retweets\").\n\t\tDocvalueFieldsWithFormat(\n\t\t\t// DocvalueField{Field: \"user\"},\n\t\t\t// DocvalueField{Field: \"retweets\", Format: \"long\"},\n\t\t\tDocvalueField{Field: \"created\", Format: \"epoch_millis\"},\n\t\t).\n\t\tPretty(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif searchResult.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := searchResult.TotalHits(), int64(3); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(searchResult.Hits.Hits), 3; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n\n\tfor _, hit := range searchResult.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n}\n\nfunc TestSearchWithDateMathIndices(t *testing.T) {\n\tclient := setupTestClient(t) //, SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\n\tctx := context.Background()\n\tnow := time.Now().UTC()\n\tindexNameToday := fmt.Sprintf(\"elastic-trail-%s\", now.Format(\"2006.01.02\"))\n\tindexNameYesterday := fmt.Sprintf(\"elastic-trail-%s\", now.AddDate(0, 0, -1).Format(\"2006.01.02\"))\n\tindexNameTomorrow := fmt.Sprintf(\"elastic-trail-%s\", now.AddDate(0, 0, +1).Format(\"2006.01.02\"))\n\n\tconst mapping = `{\n\t\"settings\":{\n\t\t\"number_of_shards\":1,\n\t\t\"number_of_replicas\":0\n\t}\n}`\n\n\t// Create indices\n\tfor i, indexName := range []string{indexNameToday, indexNameTomorrow, indexNameYesterday} {\n\t\t_, err := client.CreateIndex(indexName).Body(mapping).Do(ctx)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tdefer client.DeleteIndex(indexName).Do(ctx)\n\n\t\t// Add a document\n\t\tid := fmt.Sprintf(\"%d\", i+1)\n\t\t_, err = client.Index().Index(indexName).Id(id).BodyJson(map[string]interface{}{\n\t\t\t\"index\": indexName,\n\t\t}).Refresh(\"wait_for\").Do(ctx)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\t// Count total\n\tcnt, err := client.\n\t\tCount(indexNameYesterday, indexNameToday, indexNameTomorrow).\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif cnt != 3 {\n\t\tt.Fatalf(\"expected Count=%d; got %d\", 3, cnt)\n\t}\n\n\t// Match all should return all documents\n\tres, err := client.Search().\n\t\tIndex(\"<elastic-trail-{now/d}>\", \"<elastic-trail-{now-1d/d}>\").\n\t\tQuery(NewMatchAllQuery()).\n\t\tPretty(true).\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res.Hits == nil {\n\t\tt.Errorf(\"expected SearchResult.Hits != nil; got nil\")\n\t}\n\tif got, want := res.TotalHits(), int64(2); got != want {\n\t\tt.Errorf(\"expected SearchResult.TotalHits() = %d; got %d\", want, got)\n\t}\n\tif got, want := len(res.Hits.Hits), 2; got != want {\n\t\tt.Errorf(\"expected len(SearchResult.Hits.Hits) = %d; got %d\", want, got)\n\t}\n}\n\nfunc TestSearchResultDecode(t *testing.T) {\n\ttests := []struct {\n\t\tBody string\n\t}{\n\t\t// #0 With _shards.failures\n\t\t{\n\t\t\tBody: `{\n\t\t\t\t\"took\":1146,\n\t\t\t\t\"timed_out\":false,\n\t\t\t\t\"_shards\":{\n\t\t\t\t   \"total\":8,\n\t\t\t\t   \"successful\":6,\n\t\t\t\t   \"skipped\":0,\n\t\t\t\t   \"failed\":2,\n\t\t\t\t   \"failures\":[\n\t\t\t\t\t  {\n\t\t\t\t\t\t \"shard\":1,\n\t\t\t\t\t\t \"index\":\"l9leakip-0000001\",\n\t\t\t\t\t\t \"node\":\"AsQq1Dh2QxCSTRSLTg0vFw\",\n\t\t\t\t\t\t \"reason\":{\n\t\t\t\t\t\t\t\"type\":\"illegal_argument_exception\",\n\t\t\t\t\t\t\t\"reason\":\"The length [1119437] of field [events.summary] in doc[2524900]/index[l9leakip-0000001] exceeds the [index.highlight.max_analyzed_offset] limit [1000000]. To avoid this error, set the query parameter [max_analyzed_offset] to a value less than index setting [1000000] and this will tolerate long field values by truncating them.\"\n\t\t\t\t\t\t }\n\t\t\t\t\t  },\n\t\t\t\t\t  {\n\t\t\t\t\t\t \"shard\":3,\n\t\t\t\t\t\t \"index\":\"l9leakip-0000001\",\n\t\t\t\t\t\t \"node\":\"AsQq1Dh2QxCSTRSLTg0vFw\",\n\t\t\t\t\t\t \"reason\":{\n\t\t\t\t\t\t\t\"type\":\"illegal_argument_exception\",\n\t\t\t\t\t\t\t\"reason\":\"The length [1023566] of field [events.summary] in doc[2168434]/index[l9leakip-0000001] exceeds the [index.highlight.max_analyzed_offset] limit [1000000]. To avoid this error, set the query parameter [max_analyzed_offset] to a value less than index setting [1000000] and this will tolerate long field values by truncating them.\"\n\t\t\t\t\t\t }\n\t\t\t\t\t  }\n\t\t\t\t   ]\n\t\t\t\t},\n\t\t\t\t\"hits\":{}\n\t\t\t }`,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tvar resp SearchResult\n\t\tif err := json.Unmarshal([]byte(tt.Body), &resp); err != nil {\n\t\t\tt.Fatalf(\"case #%d: expected no error, got %v\", i, err)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "setup_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"math/rand\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n)\n\nconst (\n\ttestIndexName      = \"elastic-test\"\n\ttestIndexName2     = \"elastic-test2\"\n\ttestIndexName3     = \"elastic-test3\"\n\ttestIndexName4     = \"elastic-test4\"\n\ttestIndexName5     = \"elastic-test5\"\n\ttestIndexNameEmpty = \"elastic-test-empty\"\n\ttestMapping        = `\n{\n\t\"settings\":{\n\t\t\"number_of_shards\":1,\n\t\t\"number_of_replicas\":0\n\t},\n\t\"mappings\":{\n\t\t\"properties\":{\n\t\t\t\"user\":{\n\t\t\t\t\"type\":\"keyword\"\n\t\t\t},\n\t\t\t\"message\":{\n\t\t\t\t\"type\":\"text\",\n\t\t\t\t\"store\": true,\n\t\t\t\t\"fielddata\": true\n\t\t\t},\n\t\t\t\"tags\":{\n\t\t\t\t\"type\":\"keyword\"\n\t\t\t},\n\t\t\t\"location\":{\n\t\t\t\t\"type\":\"geo_point\"\n\t\t\t},\n\t\t\t\"suggest_field\":{\n\t\t\t\t\"type\":\"completion\"\n\t\t\t}\n\t\t}\n\t}\n}\n`\n\ttestMappingWithContext = `\n{\n\t\"settings\":{\n\t\t\"number_of_shards\":1,\n\t\t\"number_of_replicas\":0\n\t},\n\t\"mappings\":{\n\t\t\"properties\":{\n\t\t\t\"user\":{\n\t\t\t\t\"type\":\"keyword\"\n\t\t\t},\n\t\t\t\"message\":{\n\t\t\t\t\"type\":\"text\",\n\t\t\t\t\"store\": true,\n\t\t\t\t\"fielddata\": true\n\t\t\t},\n\t\t\t\"tags\":{\n\t\t\t\t\"type\":\"keyword\"\n\t\t\t},\n\t\t\t\"location\":{\n\t\t\t\t\"type\":\"geo_point\"\n\t\t\t},\n\t\t\t\"suggest_field\":{\n\t\t\t\t\"type\":\"completion\",\n\t\t\t\t\"contexts\":[\n\t\t\t\t\t{\n\t\t\t\t\t\t\"name\":\"user_name\",\n\t\t\t\t\t\t\"type\":\"category\"\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t}\n\t}\n}\n`\n\n\ttestNoSourceIndexName = \"elastic-nosource-test\"\n\ttestNoSourceMapping   = `\n{\n\t\"settings\":{\n\t\t\"number_of_shards\":1,\n\t\t\"number_of_replicas\":0\n\t},\n\t\"mappings\":{\n\t\t\"_source\": {\n\t\t\t\"enabled\": false\n\t\t},\n\t\t\"properties\":{\n\t\t\t\"user\":{\n\t\t\t\t\"type\":\"keyword\"\n\t\t\t},\n\t\t\t\"message\":{\n\t\t\t\t\"type\":\"text\",\n\t\t\t\t\"store\": true,\n\t\t\t\t\"fielddata\": true\n\t\t\t},\n\t\t\t\"tags\":{\n\t\t\t\t\"type\":\"keyword\"\n\t\t\t},\n\t\t\t\"location\":{\n\t\t\t\t\"type\":\"geo_point\"\n\t\t\t},\n\t\t\t\"suggest_field\":{\n\t\t\t\t\"type\":\"completion\",\n\t\t\t\t\"contexts\":[\n\t\t\t\t\t{\n\t\t\t\t\t\t\"name\":\"user_name\",\n\t\t\t\t\t\t\"type\":\"category\"\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t}\n\t}\n}\n`\n\n\ttestJoinIndex   = \"elastic-joins\"\n\ttestJoinMapping = `\n\t{\n\t\t\"settings\":{\n\t\t\t\"number_of_shards\":1,\n\t\t\t\"number_of_replicas\":0\n\t\t},\n\t\t\"mappings\":{\n\t\t\t\"properties\":{\n\t\t\t\t\"message\":{\n\t\t\t\t\t\"type\":\"text\"\n\t\t\t\t},\n\t\t\t\t\"my_join_field\": {\n\t\t\t\t\t\"type\": \"join\",\n\t\t\t\t\t\"relations\": {\n\t\t\t\t\t\t\"question\": \"answer\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n`\n\n\ttestOrderIndex   = \"elastic-orders\"\n\ttestOrderMapping = `\n{\n\t\"settings\":{\n\t\t\"number_of_shards\":1,\n\t\t\"number_of_replicas\":0\n\t},\n\t\"mappings\":{\n\t\t\"properties\":{\n\t\t\t\"article\":{\n\t\t\t\t\"type\":\"text\"\n\t\t\t},\n\t\t\t\"manufacturer\":{\n\t\t\t\t\"type\":\"keyword\"\n\t\t\t},\n\t\t\t\"price\":{\n\t\t\t\t\"type\":\"float\"\n\t\t\t},\n\t\t\t\"time\":{\n\t\t\t\t\"type\":\"date\",\n\t\t\t\t\"format\": \"yyyy-MM-dd\"\n\t\t\t}\n\t\t}\n\t}\n}\n`\n\n\t/*\n\t\t   \ttestDoctypeIndex   = \"elastic-doctypes\"\n\t\t   \ttestDoctypeMapping = `\n\t\t   {\n\t\t   \t\"settings\":{\n\t\t   \t\t\"number_of_shards\":1,\n\t\t   \t\t\"number_of_replicas\":0\n\t\t   \t},\n\t\t   \t\"mappings\":{\n\t\t\t\t\"properties\":{\n\t\t\t\t\t\"message\":{\n\t\t\t\t\t\t\"type\":\"text\",\n\t\t\t\t\t\t\"store\": true,\n\t\t\t\t\t\t\"fielddata\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t   \t}\n\t\t   }\n\t\t   `\n\t*/\n\n\ttestQueryIndex   = \"elastic-queries\"\n\ttestQueryMapping = `\n{\n\t\"settings\":{\n\t\t\"number_of_shards\":1,\n\t\t\"number_of_replicas\":0\n\t},\n\t\"mappings\":{\n\t\t\"properties\":{\n\t\t\t\"message\":{\n\t\t\t\t\"type\":\"text\",\n\t\t\t\t\"store\": true,\n\t\t\t\t\"fielddata\": true\n\t\t\t},\n\t\t\t\"query\": {\n\t\t\t\t\"type\":\t\"percolator\"\n\t\t\t}\n\t\t}\n\t}\n}\n`\n)\n\ntype tweet struct {\n\tUser     string        `json:\"user\"`\n\tMessage  string        `json:\"message\"`\n\tRetweets int           `json:\"retweets\"`\n\tImage    string        `json:\"image,omitempty\"`\n\tCreated  time.Time     `json:\"created,omitempty\"`\n\tTags     []string      `json:\"tags,omitempty\"`\n\tLocation string        `json:\"location,omitempty\"`\n\tSuggest  *SuggestField `json:\"suggest_field,omitempty\"`\n}\n\nfunc (t tweet) String() string {\n\treturn fmt.Sprintf(\"tweet{User:%q,Message:%q,Retweets:%d}\", t.User, t.Message, t.Retweets)\n}\n\ntype joinDoc struct {\n\tMessage   string      `json:\"message\"`\n\tJoinField interface{} `json:\"my_join_field,omitempty\"`\n}\n\ntype joinField struct {\n\tName   string `json:\"name\"`\n\tParent string `json:\"parent,omitempty\"`\n}\n\ntype order struct {\n\tArticle      string  `json:\"article\"`\n\tManufacturer string  `json:\"manufacturer\"`\n\tPrice        float64 `json:\"price\"`\n\tTime         string  `json:\"time,omitempty\"`\n}\n\nfunc (o order) String() string {\n\treturn fmt.Sprintf(\"order{Article:%q,Manufacturer:%q,Price:%v,Time:%v}\", o.Article, o.Manufacturer, o.Price, o.Time)\n}\n\n// doctype is required for Percolate tests.\ntype doctype struct {\n\tMessage string `json:\"message\"`\n}\n\nfunc isCI() bool {\n\treturn os.Getenv(\"TRAVIS\") != \"\" || os.Getenv(\"CI\") != \"\" || os.Getenv(\"GITHUB_ACTIONS\") != \"\"\n}\n\ntype logger interface {\n\tError(args ...interface{})\n\tErrorf(format string, args ...interface{})\n\tFatal(args ...interface{})\n\tFatalf(format string, args ...interface{})\n\tFail()\n\tFailNow()\n\tLog(args ...interface{})\n\tLogf(format string, args ...interface{})\n}\n\nfunc boolPtr(b bool) *bool { return &b }\n\n// strictDecoder returns an error if any JSON fields aren't decoded.\ntype strictDecoder struct{}\n\nfunc (d *strictDecoder) Decode(data []byte, v interface{}) error {\n\tdec := json.NewDecoder(bytes.NewReader(data))\n\tdec.DisallowUnknownFields()\n\treturn dec.Decode(v)\n}\n\nvar (\n\tlogDeprecations = flag.String(\"deprecations\", \"off\", \"log or fail on deprecation warnings\")\n\tlogTypesRemoval = flag.Bool(\"types-removal\", false, \"log deprecation warnings regarding types removal\")\n\tstrict          = flag.Bool(\"strict-decoder\", false, \"treat missing unknown fields in response as errors\")\n\tnoSniff         = flag.Bool(\"no-sniff\", false, \"allows to disable sniffing globally\")\n\tnoHealthcheck   = flag.Bool(\"no-healthcheck\", false, \"allows to disable healthchecks globally\")\n)\n\nfunc setupTestClient(t logger, options ...ClientOptionFunc) (client *Client) {\n\tvar err error\n\n\tif *noSniff {\n\t\toptions = append(options, SetSniff(false))\n\t}\n\tif *noHealthcheck {\n\t\toptions = append(options, SetHealthcheck(false))\n\t}\n\n\tclient, err = NewClient(options...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Use strict JSON decoder (unless a specific decoder has been specified already)\n\tif *strict {\n\t\tif client.decoder == nil {\n\t\t\tclient.decoder = &strictDecoder{}\n\t\t} else if _, ok := client.decoder.(*DefaultDecoder); ok {\n\t\t\tclient.decoder = &strictDecoder{}\n\t\t}\n\t}\n\n\t// Log deprecations during tests\n\tif loglevel := *logDeprecations; loglevel != \"off\" {\n\t\tclient.deprecationlog = func(req *http.Request, res *http.Response) {\n\t\t\tfor _, warning := range res.Header[\"Warning\"] {\n\t\t\t\tif !*logTypesRemoval && strings.Contains(warning, \"[types removal]\") {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tswitch loglevel {\n\t\t\t\tdefault:\n\t\t\t\t\tt.Logf(\"[%s] Deprecation warning: %s\", req.URL, warning)\n\t\t\t\tcase \"fail\", \"error\":\n\t\t\t\t\tt.Errorf(\"[%s] Deprecation warning: %s\", req.URL, warning)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tclient.DeleteIndex(testIndexName).Do(context.TODO())\n\tclient.DeleteIndex(testIndexName2).Do(context.TODO())\n\tclient.DeleteIndex(testIndexName3).Do(context.TODO())\n\tclient.DeleteIndex(testIndexName4).Do(context.TODO())\n\tclient.DeleteIndex(testIndexName5).Do(context.TODO())\n\tclient.DeleteIndex(testIndexNameEmpty).Do(context.TODO())\n\tclient.DeleteIndex(testOrderIndex).Do(context.TODO())\n\tclient.DeleteIndex(testNoSourceIndexName).Do(context.TODO())\n\t//client.DeleteIndex(testDoctypeIndex).Do(context.TODO())\n\tclient.DeleteIndex(testQueryIndex).Do(context.TODO())\n\tclient.DeleteIndex(testJoinIndex).Do(context.TODO())\n\n\treturn client\n}\n\nfunc setupTestClientAndCreateIndex(t logger, options ...ClientOptionFunc) *Client {\n\tclient := setupTestClient(t, options...)\n\n\t// Create index\n\tcreateIndex, err := client.CreateIndex(testIndexName).Body(testMapping).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndex)\n\t}\n\n\t// Create second index\n\tcreateIndex2, err := client.CreateIndex(testIndexName2).Body(testMappingWithContext).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndex2 == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndex2)\n\t}\n\n\t// Create no source index\n\tcreateNoSourceIndex, err := client.CreateIndex(testNoSourceIndexName).Body(testNoSourceMapping).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createNoSourceIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createNoSourceIndex)\n\t}\n\n\t// Create order index\n\tcreateOrderIndex, err := client.CreateIndex(testOrderIndex).Body(testOrderMapping).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createOrderIndex == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createOrderIndex)\n\t}\n\n\t// Create empty index\n\tcreateIndexEmpty, err := client.CreateIndex(testIndexNameEmpty).Body(testMapping).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createIndexEmpty == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", createIndexEmpty)\n\t}\n\n\treturn client\n}\n\nfunc setupTestClientAndCreateIndexAndLog(t logger, options ...ClientOptionFunc) *Client {\n\treturn setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n}\n\nvar _ = setupTestClientAndCreateIndexAndLog // remove unused warning in staticcheck\n\nfunc setupTestClientAndCreateIndexAndAddDocs(t logger, options ...ClientOptionFunc) *Client {\n\tclient := setupTestClientAndCreateIndex(t, options...)\n\n\t// Add tweets\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\", Retweets: 108, Tags: []string{\"golang\", \"elasticsearch\"}}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\", Retweets: 0, Tags: []string{\"golang\"}}\n\ttweet3 := tweet{User: \"sandrae\", Message: \"Cycling is fun.\", Retweets: 12, Tags: []string{\"sports\", \"cycling\"}}\n\n\t_, err := client.Index().Index(testIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_, err = client.Index().Index(testIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_, err = client.Index().Index(testIndexName).Id(\"3\").Routing(\"someroutingkey\").BodyJson(&tweet3).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Add orders\n\tvar orders []order\n\torders = append(orders, order{Article: \"Apple MacBook\", Manufacturer: \"Apple\", Price: 1290, Time: \"2015-01-18\"})\n\torders = append(orders, order{Article: \"Paper\", Manufacturer: \"Canon\", Price: 100, Time: \"2015-03-01\"})\n\torders = append(orders, order{Article: \"Apple iPad\", Manufacturer: \"Apple\", Price: 499, Time: \"2015-04-12\"})\n\torders = append(orders, order{Article: \"Dell XPS 13\", Manufacturer: \"Dell\", Price: 1600, Time: \"2015-04-18\"})\n\torders = append(orders, order{Article: \"Apple Watch\", Manufacturer: \"Apple\", Price: 349, Time: \"2015-04-29\"})\n\torders = append(orders, order{Article: \"Samsung TV\", Manufacturer: \"Samsung\", Price: 790, Time: \"2015-05-03\"})\n\torders = append(orders, order{Article: \"Hoodie\", Manufacturer: \"h&m\", Price: 49, Time: \"2015-06-03\"})\n\torders = append(orders, order{Article: \"T-Shirt\", Manufacturer: \"h&m\", Price: 19, Time: \"2015-06-18\"})\n\tfor i, o := range orders {\n\t\tid := fmt.Sprintf(\"%d\", i)\n\t\t_, err = client.Index().Index(testOrderIndex).Id(id).BodyJson(&o).Do(context.TODO())\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\t// Refresh\n\t_, err = client.Refresh().Index(testIndexName, testOrderIndex).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\treturn client\n}\n\nfunc setupTestClientAndCreateIndexAndAddDocsNoSource(t logger, options ...ClientOptionFunc) *Client {\n\tclient := setupTestClientAndCreateIndex(t, options...)\n\n\t// Add tweets\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\ttweet2 := tweet{User: \"olivere\", Message: \"Another unrelated topic.\"}\n\n\t_, err := client.Index().Index(testNoSourceIndexName).Id(\"1\").BodyJson(&tweet1).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_, err = client.Index().Index(testNoSourceIndexName).Id(\"2\").BodyJson(&tweet2).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t// Refresh\n\t_, err = client.Refresh().Index(testNoSourceIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\treturn client\n}\n\nfunc setupTestClientForXpackSecurity(t logger) (client *Client) {\n\tvar err error\n\t// Set URL and Auth to use the platinum ES cluster\n\toptions := []ClientOptionFunc{SetURL(\"http://127.0.0.1:9210\"), SetBasicAuth(\"elastic\", \"elastic\")}\n\n\tclient, err = NewClient(options...)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\treturn client\n}\n\nvar letters = []rune(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\")\n\nfunc randomString(n int) string {\n\tb := make([]rune, n)\n\tfor i := range b {\n\t\tb[i] = letters[rand.Intn(len(letters))]\n\t}\n\treturn string(b)\n}\n\ntype lexicographically struct {\n\tstrings []string\n}\n\nfunc (l lexicographically) Len() int {\n\treturn len(l.strings)\n}\n\nfunc (l lexicographically) Less(i, j int) bool {\n\treturn l.strings[i] < l.strings[j]\n}\n\nfunc (l lexicographically) Swap(i, j int) {\n\tl.strings[i], l.strings[j] = l.strings[j], l.strings[i]\n}\n"
  },
  {
    "path": "snapshot_create.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SnapshotCreateService is documented at https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-snapshots.html.\ntype SnapshotCreateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository        string\n\tsnapshot          string\n\tmasterTimeout     string\n\twaitForCompletion *bool\n\tbodyJson          interface{}\n\tbodyString        string\n}\n\n// NewSnapshotCreateService creates a new SnapshotCreateService.\nfunc NewSnapshotCreateService(client *Client) *SnapshotCreateService {\n\treturn &SnapshotCreateService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SnapshotCreateService) Pretty(pretty bool) *SnapshotCreateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SnapshotCreateService) Human(human bool) *SnapshotCreateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SnapshotCreateService) ErrorTrace(errorTrace bool) *SnapshotCreateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SnapshotCreateService) FilterPath(filterPath ...string) *SnapshotCreateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SnapshotCreateService) Header(name string, value string) *SnapshotCreateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SnapshotCreateService) Headers(headers http.Header) *SnapshotCreateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository is the repository name.\nfunc (s *SnapshotCreateService) Repository(repository string) *SnapshotCreateService {\n\ts.repository = repository\n\treturn s\n}\n\n// Snapshot is the snapshot name.\nfunc (s *SnapshotCreateService) Snapshot(snapshot string) *SnapshotCreateService {\n\ts.snapshot = snapshot\n\treturn s\n}\n\n// MasterTimeout is documented as: Explicit operation timeout for connection to master node.\nfunc (s *SnapshotCreateService) MasterTimeout(masterTimeout string) *SnapshotCreateService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// WaitForCompletion is documented as: Should this request wait until the operation has completed before returning.\nfunc (s *SnapshotCreateService) WaitForCompletion(waitForCompletion bool) *SnapshotCreateService {\n\ts.waitForCompletion = &waitForCompletion\n\treturn s\n}\n\n// BodyJson is documented as: The snapshot definition.\nfunc (s *SnapshotCreateService) BodyJson(body interface{}) *SnapshotCreateService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is documented as: The snapshot definition.\nfunc (s *SnapshotCreateService) BodyString(body string) *SnapshotCreateService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SnapshotCreateService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_snapshot/{repository}/{snapshot}\", map[string]string{\n\t\t\"snapshot\":   s.snapshot,\n\t\t\"repository\": s.repository,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif v := s.waitForCompletion; v != nil {\n\t\tparams.Set(\"wait_for_completion\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SnapshotCreateService) Validate() error {\n\tvar invalid []string\n\tif s.repository == \"\" {\n\t\tinvalid = append(invalid, \"Repository\")\n\t}\n\tif s.snapshot == \"\" {\n\t\tinvalid = append(invalid, \"Snapshot\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *SnapshotCreateService) Do(ctx context.Context) (*SnapshotCreateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SnapshotCreateResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// SnapshotShardFailure stores information about failures that occurred during shard snapshotting process.\ntype SnapshotShardFailure struct {\n\tIndex     string `json:\"index\"`\n\tIndexUUID string `json:\"index_uuid\"`\n\tShardID   int    `json:\"shard_id\"`\n\tReason    string `json:\"reason\"`\n\tNodeID    string `json:\"node_id\"`\n\tStatus    string `json:\"status\"`\n}\n\n// SnapshotCreateResponse is the response of SnapshotCreateService.Do.\ntype SnapshotCreateResponse struct {\n\t// Accepted indicates whether the request was accepted by elasticsearch.\n\t// It's available when waitForCompletion is false.\n\tAccepted *bool `json:\"accepted\"`\n\n\t// Snapshot is available when waitForCompletion is true.\n\tSnapshot *Snapshot `json:\"snapshot\"`\n}\n"
  },
  {
    "path": "snapshot_create_repository.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SnapshotCreateRepositoryService creates a snapshot repository.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-snapshots.html\n// for details.\ntype SnapshotCreateRepositoryService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository    string\n\tmasterTimeout string\n\ttimeout       string\n\tverify        *bool\n\ttyp           string\n\tsettings      map[string]interface{}\n\tbodyJson      interface{}\n\tbodyString    string\n}\n\n// NewSnapshotCreateRepositoryService creates a new SnapshotCreateRepositoryService.\nfunc NewSnapshotCreateRepositoryService(client *Client) *SnapshotCreateRepositoryService {\n\treturn &SnapshotCreateRepositoryService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SnapshotCreateRepositoryService) Pretty(pretty bool) *SnapshotCreateRepositoryService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SnapshotCreateRepositoryService) Human(human bool) *SnapshotCreateRepositoryService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SnapshotCreateRepositoryService) ErrorTrace(errorTrace bool) *SnapshotCreateRepositoryService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SnapshotCreateRepositoryService) FilterPath(filterPath ...string) *SnapshotCreateRepositoryService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SnapshotCreateRepositoryService) Header(name string, value string) *SnapshotCreateRepositoryService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SnapshotCreateRepositoryService) Headers(headers http.Header) *SnapshotCreateRepositoryService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository is the repository name.\nfunc (s *SnapshotCreateRepositoryService) Repository(repository string) *SnapshotCreateRepositoryService {\n\ts.repository = repository\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *SnapshotCreateRepositoryService) MasterTimeout(masterTimeout string) *SnapshotCreateRepositoryService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *SnapshotCreateRepositoryService) Timeout(timeout string) *SnapshotCreateRepositoryService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// Verify indicates whether to verify the repository after creation.\nfunc (s *SnapshotCreateRepositoryService) Verify(verify bool) *SnapshotCreateRepositoryService {\n\ts.verify = &verify\n\treturn s\n}\n\n// Type sets the snapshot repository type, e.g. \"fs\".\nfunc (s *SnapshotCreateRepositoryService) Type(typ string) *SnapshotCreateRepositoryService {\n\ts.typ = typ\n\treturn s\n}\n\n// Settings sets all settings of the snapshot repository.\nfunc (s *SnapshotCreateRepositoryService) Settings(settings map[string]interface{}) *SnapshotCreateRepositoryService {\n\ts.settings = settings\n\treturn s\n}\n\n// Setting sets a single settings of the snapshot repository.\nfunc (s *SnapshotCreateRepositoryService) Setting(name string, value interface{}) *SnapshotCreateRepositoryService {\n\tif s.settings == nil {\n\t\ts.settings = make(map[string]interface{})\n\t}\n\ts.settings[name] = value\n\treturn s\n}\n\n// BodyJson is documented as: The repository definition.\nfunc (s *SnapshotCreateRepositoryService) BodyJson(body interface{}) *SnapshotCreateRepositoryService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is documented as: The repository definition.\nfunc (s *SnapshotCreateRepositoryService) BodyString(body string) *SnapshotCreateRepositoryService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SnapshotCreateRepositoryService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_snapshot/{repository}\", map[string]string{\n\t\t\"repository\": s.repository,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif v := s.verify; v != nil {\n\t\tparams.Set(\"verify\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// buildBody builds the body for the operation.\nfunc (s *SnapshotCreateRepositoryService) buildBody() (interface{}, error) {\n\tif s.bodyJson != nil {\n\t\treturn s.bodyJson, nil\n\t}\n\tif s.bodyString != \"\" {\n\t\treturn s.bodyString, nil\n\t}\n\n\tbody := map[string]interface{}{\n\t\t\"type\": s.typ,\n\t}\n\tif len(s.settings) > 0 {\n\t\tbody[\"settings\"] = s.settings\n\t}\n\treturn body, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SnapshotCreateRepositoryService) Validate() error {\n\tvar invalid []string\n\tif s.repository == \"\" {\n\t\tinvalid = append(invalid, \"Repository\")\n\t}\n\tif s.bodyString == \"\" && s.bodyJson == nil && len(s.settings) == 0 {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *SnapshotCreateRepositoryService) Do(ctx context.Context) (*SnapshotCreateRepositoryResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tbody, err := s.buildBody()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SnapshotCreateRepositoryResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// SnapshotCreateRepositoryResponse is the response of SnapshotCreateRepositoryService.Do.\ntype SnapshotCreateRepositoryResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "snapshot_create_repository_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSnapshotPutRepositoryURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository string\n\t\tExpected   string\n\t}{\n\t\t{\n\t\t\t\"repo\",\n\t\t\t\"/_snapshot/repo\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.SnapshotCreateRepository(test.Repository).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestSnapshotPutRepositoryBodyWithSettings(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\tservice := client.SnapshotCreateRepository(\"my_backup\")\n\tservice = service.Type(\"fs\").\n\t\tSettings(map[string]interface{}{\n\t\t\t\"location\": \"my_backup_location\",\n\t\t\t\"compress\": false,\n\t\t}).\n\t\tSetting(\"compress\", true).\n\t\tSetting(\"chunk_size\", 16*1024*1024)\n\n\tif err := service.Validate(); err != nil {\n\t\tt.Fatal(err)\n\t}\n\tsrc, err := service.buildBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"settings\":{\"chunk_size\":16777216,\"compress\":true,\"location\":\"my_backup_location\"},\"type\":\"fs\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "snapshot_create_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"net/url\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestSnapshotValidate(t *testing.T) {\n\tvar client *Client\n\n\terr := NewSnapshotCreateService(client).Validate()\n\tgot := err.Error()\n\texpected := \"missing required fields: [Repository Snapshot]\"\n\tif got != expected {\n\t\tt.Errorf(\"expected %q; got: %q\", expected, got)\n\t}\n}\n\nfunc TestSnapshotPutURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository        string\n\t\tSnapshot          string\n\t\tPretty            bool\n\t\tMasterTimeout     string\n\t\tWaitForCompletion bool\n\t\tExpectedPath      string\n\t\tExpectedParams    url.Values\n\t}{\n\t\t{\n\t\t\tRepository:        \"repo\",\n\t\t\tSnapshot:          \"snapshot_of_sunday\",\n\t\t\tPretty:            true,\n\t\t\tMasterTimeout:     \"60s\",\n\t\t\tWaitForCompletion: true,\n\t\t\tExpectedPath:      \"/_snapshot/repo/snapshot_of_sunday\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"pretty\":              []string{\"true\"},\n\t\t\t\t\"master_timeout\":      []string{\"60s\"},\n\t\t\t\t\"wait_for_completion\": []string{\"true\"},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, params, err := client.SnapshotCreate(test.Repository, test.Snapshot).\n\t\t\tPretty(test.Pretty).\n\t\t\tMasterTimeout(test.MasterTimeout).\n\t\t\tWaitForCompletion(test.WaitForCompletion).\n\t\t\tbuildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.ExpectedPath {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.ExpectedPath, path)\n\t\t}\n\t\tif !reflect.DeepEqual(params, test.ExpectedParams) {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.ExpectedParams, params)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "snapshot_delete.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SnapshotDeleteService deletes a snapshot from a snapshot repository.\n// It is documented at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-snapshots.html.\ntype SnapshotDeleteService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository string\n\tsnapshot   string\n}\n\n// NewSnapshotDeleteService creates a new SnapshotDeleteService.\nfunc NewSnapshotDeleteService(client *Client) *SnapshotDeleteService {\n\treturn &SnapshotDeleteService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SnapshotDeleteService) Pretty(pretty bool) *SnapshotDeleteService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SnapshotDeleteService) Human(human bool) *SnapshotDeleteService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SnapshotDeleteService) ErrorTrace(errorTrace bool) *SnapshotDeleteService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SnapshotDeleteService) FilterPath(filterPath ...string) *SnapshotDeleteService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SnapshotDeleteService) Header(name string, value string) *SnapshotDeleteService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SnapshotDeleteService) Headers(headers http.Header) *SnapshotDeleteService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository is the repository name.\nfunc (s *SnapshotDeleteService) Repository(repository string) *SnapshotDeleteService {\n\ts.repository = repository\n\treturn s\n}\n\n// Snapshot is the snapshot name.\nfunc (s *SnapshotDeleteService) Snapshot(snapshot string) *SnapshotDeleteService {\n\ts.snapshot = snapshot\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SnapshotDeleteService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_snapshot/{repository}/{snapshot}\", map[string]string{\n\t\t\"repository\": s.repository,\n\t\t\"snapshot\":   s.snapshot,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\treturn path, url.Values{}, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SnapshotDeleteService) Validate() error {\n\tvar invalid []string\n\tif s.repository == \"\" {\n\t\tinvalid = append(invalid, \"Repository\")\n\t}\n\tif s.snapshot == \"\" {\n\t\tinvalid = append(invalid, \"Snapshot\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *SnapshotDeleteService) Do(ctx context.Context) (*SnapshotDeleteResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod: \"DELETE\",\n\t\tPath:   path,\n\t\tParams: params,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SnapshotDeleteResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// SnapshotDeleteResponse is the response of SnapshotDeleteService.Do.\ntype SnapshotDeleteResponse struct {\n\tAcknowledged bool `json:\"acknowledged\"`\n}\n"
  },
  {
    "path": "snapshot_delete_repository.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SnapshotDeleteRepositoryService deletes a snapshot repository.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-snapshots.html\n// for details.\ntype SnapshotDeleteRepositoryService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository    []string\n\tmasterTimeout string\n\ttimeout       string\n}\n\n// NewSnapshotDeleteRepositoryService creates a new SnapshotDeleteRepositoryService.\nfunc NewSnapshotDeleteRepositoryService(client *Client) *SnapshotDeleteRepositoryService {\n\treturn &SnapshotDeleteRepositoryService{\n\t\tclient:     client,\n\t\trepository: make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SnapshotDeleteRepositoryService) Pretty(pretty bool) *SnapshotDeleteRepositoryService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SnapshotDeleteRepositoryService) Human(human bool) *SnapshotDeleteRepositoryService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SnapshotDeleteRepositoryService) ErrorTrace(errorTrace bool) *SnapshotDeleteRepositoryService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SnapshotDeleteRepositoryService) FilterPath(filterPath ...string) *SnapshotDeleteRepositoryService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SnapshotDeleteRepositoryService) Header(name string, value string) *SnapshotDeleteRepositoryService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SnapshotDeleteRepositoryService) Headers(headers http.Header) *SnapshotDeleteRepositoryService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository is the list of repository names.\nfunc (s *SnapshotDeleteRepositoryService) Repository(repositories ...string) *SnapshotDeleteRepositoryService {\n\ts.repository = append(s.repository, repositories...)\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *SnapshotDeleteRepositoryService) MasterTimeout(masterTimeout string) *SnapshotDeleteRepositoryService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *SnapshotDeleteRepositoryService) Timeout(timeout string) *SnapshotDeleteRepositoryService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SnapshotDeleteRepositoryService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_snapshot/{repository}\", map[string]string{\n\t\t\"repository\": strings.Join(s.repository, \",\"),\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SnapshotDeleteRepositoryService) Validate() error {\n\tvar invalid []string\n\tif len(s.repository) == 0 {\n\t\tinvalid = append(invalid, \"Repository\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *SnapshotDeleteRepositoryService) Do(ctx context.Context) (*SnapshotDeleteRepositoryResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SnapshotDeleteRepositoryResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// SnapshotDeleteRepositoryResponse is the response of SnapshotDeleteRepositoryService.Do.\ntype SnapshotDeleteRepositoryResponse struct {\n\tAcknowledged       bool   `json:\"acknowledged\"`\n\tShardsAcknowledged bool   `json:\"shards_acknowledged\"`\n\tIndex              string `json:\"index,omitempty\"`\n}\n"
  },
  {
    "path": "snapshot_delete_repository_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestSnapshotDeleteRepositoryURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository []string\n\t\tExpected   string\n\t}{\n\t\t{\n\t\t\t[]string{\"repo1\"},\n\t\t\t\"/_snapshot/repo1\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"repo1\", \"repo2\"},\n\t\t\t\"/_snapshot/repo1%2Crepo2\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.SnapshotDeleteRepository(test.Repository...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "snapshot_delete_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"net/url\"\n\t\"testing\"\n)\n\nfunc TestSnapshotRepoValidate(t *testing.T) {\n\tvar client *Client\n\n\terr := NewSnapshotDeleteService(client).Validate()\n\tgot := err.Error()\n\texpected := \"missing required fields: [Repository Snapshot]\"\n\tif got != expected {\n\t\tt.Errorf(\"expected %q; got: %q\", expected, got)\n\t}\n}\n\nfunc TestSnapshotDeleteURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository     string\n\t\tSnapshot       string\n\t\tExpectedPath   string\n\t\tExpectedParams url.Values\n\t}{\n\t\t{\n\t\t\tRepository:   \"repo\",\n\t\t\tSnapshot:     \"snapshot_of_sunday\",\n\t\t\tExpectedPath: \"/_snapshot/repo/snapshot_of_sunday\",\n\t\t},\n\t\t{\n\t\t\tRepository:   \"repö\",\n\t\t\tSnapshot:     \"001\",\n\t\t\tExpectedPath: \"/_snapshot/rep%C3%B6/001\",\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tpath, _, err := client.SnapshotDelete(tt.Repository, tt.Snapshot).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != tt.ExpectedPath {\n\t\t\tt.Errorf(\"expected %q; got: %q\", tt.ExpectedPath, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "snapshot_get.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SnapshotGetService lists the snapshots on a repository\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-snapshots.html\n// for details.\ntype SnapshotGetService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository        string\n\tsnapshot          []string\n\tmasterTimeout     string\n\tignoreUnavailable *bool\n\tverbose           *bool\n}\n\n// NewSnapshotGetService creates a new SnapshotGetService.\nfunc NewSnapshotGetService(client *Client) *SnapshotGetService {\n\treturn &SnapshotGetService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SnapshotGetService) Pretty(pretty bool) *SnapshotGetService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SnapshotGetService) Human(human bool) *SnapshotGetService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SnapshotGetService) ErrorTrace(errorTrace bool) *SnapshotGetService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SnapshotGetService) FilterPath(filterPath ...string) *SnapshotGetService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SnapshotGetService) Header(name string, value string) *SnapshotGetService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SnapshotGetService) Headers(headers http.Header) *SnapshotGetService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository is the repository name.\nfunc (s *SnapshotGetService) Repository(repository string) *SnapshotGetService {\n\ts.repository = repository\n\treturn s\n}\n\n// Snapshot is the list of snapshot names. If not set, defaults to all snapshots.\nfunc (s *SnapshotGetService) Snapshot(snapshots ...string) *SnapshotGetService {\n\ts.snapshot = append(s.snapshot, snapshots...)\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *SnapshotGetService) MasterTimeout(masterTimeout string) *SnapshotGetService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IgnoreUnavailable specifies whether to ignore unavailable snapshots, defaults to false\nfunc (s *SnapshotGetService) IgnoreUnavailable(ignoreUnavailable bool) *SnapshotGetService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// Verbose specifies whether to show verbose snapshot info or only show the basic info found in the repository index blob\nfunc (s *SnapshotGetService) Verbose(verbose bool) *SnapshotGetService {\n\ts.verbose = &verbose\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SnapshotGetService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.snapshot) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_snapshot/{repository}/{snapshot}\", map[string]string{\n\t\t\t\"repository\": s.repository,\n\t\t\t\"snapshot\":   strings.Join(s.snapshot, \",\"),\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/_snapshot/{repository}/_all\", map[string]string{\n\t\t\t\"repository\": s.repository,\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif v := s.ignoreUnavailable; v != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*v))\n\t}\n\tif v := s.verbose; v != nil {\n\t\tparams.Set(\"verbose\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SnapshotGetService) Validate() error {\n\tvar invalid []string\n\tif s.repository == \"\" {\n\t\tinvalid = append(invalid, \"Repository\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *SnapshotGetService) Do(ctx context.Context) (*SnapshotGetResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SnapshotGetResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// SnapshotGetResponse is the response of SnapshotGetService.Do.\ntype SnapshotGetResponse struct {\n\tSnapshots []*Snapshot `json:\"snapshots\"`\n}\n\n// Snapshot contains all information about a single snapshot\ntype Snapshot struct {\n\tSnapshot          string                 `json:\"snapshot\"`\n\tUUID              string                 `json:\"uuid\"`\n\tVersionID         int                    `json:\"version_id\"`\n\tVersion           string                 `json:\"version\"`\n\tIndices           []string               `json:\"indices\"`\n\tState             string                 `json:\"state\"`\n\tReason            string                 `json:\"reason\"`\n\tStartTime         time.Time              `json:\"start_time\"`\n\tStartTimeInMillis int64                  `json:\"start_time_in_millis\"`\n\tEndTime           time.Time              `json:\"end_time\"`\n\tEndTimeInMillis   int64                  `json:\"end_time_in_millis\"`\n\tDurationInMillis  int64                  `json:\"duration_in_millis\"`\n\tFailures          []SnapshotShardFailure `json:\"failures\"`\n\tShards            *ShardsInfo            `json:\"shards\"`\n}\n"
  },
  {
    "path": "snapshot_get_repository.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SnapshotGetRepositoryService reads a snapshot repository.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-snapshots.html\n// for details.\ntype SnapshotGetRepositoryService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository    []string\n\tlocal         *bool\n\tmasterTimeout string\n}\n\n// NewSnapshotGetRepositoryService creates a new SnapshotGetRepositoryService.\nfunc NewSnapshotGetRepositoryService(client *Client) *SnapshotGetRepositoryService {\n\treturn &SnapshotGetRepositoryService{\n\t\tclient:     client,\n\t\trepository: make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SnapshotGetRepositoryService) Pretty(pretty bool) *SnapshotGetRepositoryService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SnapshotGetRepositoryService) Human(human bool) *SnapshotGetRepositoryService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SnapshotGetRepositoryService) ErrorTrace(errorTrace bool) *SnapshotGetRepositoryService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SnapshotGetRepositoryService) FilterPath(filterPath ...string) *SnapshotGetRepositoryService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SnapshotGetRepositoryService) Header(name string, value string) *SnapshotGetRepositoryService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SnapshotGetRepositoryService) Headers(headers http.Header) *SnapshotGetRepositoryService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository is the list of repository names.\nfunc (s *SnapshotGetRepositoryService) Repository(repositories ...string) *SnapshotGetRepositoryService {\n\ts.repository = append(s.repository, repositories...)\n\treturn s\n}\n\n// Local indicates whether to return local information, i.e. do not retrieve the state from master node (default: false).\nfunc (s *SnapshotGetRepositoryService) Local(local bool) *SnapshotGetRepositoryService {\n\ts.local = &local\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *SnapshotGetRepositoryService) MasterTimeout(masterTimeout string) *SnapshotGetRepositoryService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SnapshotGetRepositoryService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.repository) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_snapshot/{repository}\", map[string]string{\n\t\t\t\"repository\": strings.Join(s.repository, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_snapshot\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SnapshotGetRepositoryService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *SnapshotGetRepositoryService) Do(ctx context.Context) (SnapshotGetRepositoryResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret SnapshotGetRepositoryResponse\n\tif err := json.Unmarshal(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// SnapshotGetRepositoryResponse is the response of SnapshotGetRepositoryService.Do.\ntype SnapshotGetRepositoryResponse map[string]*SnapshotRepositoryMetaData\n\n// SnapshotRepositoryMetaData contains all information about\n// a single snapshot repository.\ntype SnapshotRepositoryMetaData struct {\n\tType     string                 `json:\"type\"`\n\tSettings map[string]interface{} `json:\"settings,omitempty\"`\n}\n"
  },
  {
    "path": "snapshot_get_repository_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestSnapshotGetRepositoryURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository []string\n\t\tExpected   string\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t\"/_snapshot\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"repo1\"},\n\t\t\t\"/_snapshot/repo1\",\n\t\t},\n\t\t{\n\t\t\t[]string{\"repo1\", \"repo2\"},\n\t\t\t\"/_snapshot/repo1%2Crepo2\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.SnapshotGetRepository(test.Repository...).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "snapshot_get_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"net/url\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestSnapshotGetValidate(t *testing.T) {\n\tvar client *Client\n\n\terr := NewSnapshotGetService(client).Validate()\n\tgot := err.Error()\n\texpected := \"missing required fields: [Repository]\"\n\tif got != expected {\n\t\tt.Errorf(\"expected %q; got: %q\", expected, got)\n\t}\n}\n\nfunc TestSnapshotGetURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository        string\n\t\tSnapshot          []string\n\t\tMasterTimeout     string\n\t\tIgnoreUnavailable bool\n\t\tVerbose           bool\n\t\tExpectedPath      string\n\t\tExpectedParams    url.Values\n\t}{\n\t\t{\n\t\t\tRepository:        \"repo\",\n\t\t\tSnapshot:          []string{},\n\t\t\tMasterTimeout:     \"60s\",\n\t\t\tIgnoreUnavailable: true,\n\t\t\tVerbose:           true,\n\t\t\tExpectedPath:      \"/_snapshot/repo/_all\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"master_timeout\":     []string{\"60s\"},\n\t\t\t\t\"ignore_unavailable\": []string{\"true\"},\n\t\t\t\t\"verbose\":            []string{\"true\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tRepository:        \"repo\",\n\t\t\tSnapshot:          []string{\"snapA\", \"snapB\"},\n\t\t\tMasterTimeout:     \"60s\",\n\t\t\tIgnoreUnavailable: true,\n\t\t\tVerbose:           true,\n\t\t\tExpectedPath:      \"/_snapshot/repo/snapA%2CsnapB\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"master_timeout\":     []string{\"60s\"},\n\t\t\t\t\"ignore_unavailable\": []string{\"true\"},\n\t\t\t\t\"verbose\":            []string{\"true\"},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, params, err := client.SnapshotGet(test.Repository).\n\t\t\tMasterTimeout(test.MasterTimeout).\n\t\t\tSnapshot(test.Snapshot...).\n\t\t\tIgnoreUnavailable(true).\n\t\t\tVerbose(true).\n\t\t\tbuildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.ExpectedPath {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.ExpectedPath, path)\n\t\t}\n\t\tif !reflect.DeepEqual(params, test.ExpectedParams) {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.ExpectedParams, params)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "snapshot_restore.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SnapshotRestoreService restores a snapshot from a snapshot repository.\n//\n// It is documented at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.1/modules-snapshots.html#_restore.\ntype SnapshotRestoreService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository         string\n\tsnapshot           string\n\tmasterTimeout      string\n\twaitForCompletion  *bool\n\tignoreUnavailable  *bool\n\tpartial            *bool\n\tincludeAliases     *bool\n\tincludeGlobalState *bool\n\tbodyString         string\n\trenamePattern      string\n\trenameReplacement  string\n\tindices            []string\n\tindexSettings      map[string]interface{}\n}\n\n// NewSnapshotCreateService creates a new SnapshotRestoreService.\nfunc NewSnapshotRestoreService(client *Client) *SnapshotRestoreService {\n\treturn &SnapshotRestoreService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SnapshotRestoreService) Pretty(pretty bool) *SnapshotRestoreService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SnapshotRestoreService) Human(human bool) *SnapshotRestoreService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SnapshotRestoreService) ErrorTrace(errorTrace bool) *SnapshotRestoreService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SnapshotRestoreService) FilterPath(filterPath ...string) *SnapshotRestoreService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SnapshotRestoreService) Header(name string, value string) *SnapshotRestoreService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SnapshotRestoreService) Headers(headers http.Header) *SnapshotRestoreService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository name.\nfunc (s *SnapshotRestoreService) Repository(repository string) *SnapshotRestoreService {\n\ts.repository = repository\n\treturn s\n}\n\n// Snapshot name.\nfunc (s *SnapshotRestoreService) Snapshot(snapshot string) *SnapshotRestoreService {\n\ts.snapshot = snapshot\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *SnapshotRestoreService) MasterTimeout(masterTimeout string) *SnapshotRestoreService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// WaitForCompletion indicates whether this request should wait until the operation has\n// completed before returning.\nfunc (s *SnapshotRestoreService) WaitForCompletion(waitForCompletion bool) *SnapshotRestoreService {\n\ts.waitForCompletion = &waitForCompletion\n\treturn s\n}\n\n// Indices sets the name of the indices that should be restored from the snapshot.\nfunc (s *SnapshotRestoreService) Indices(indices ...string) *SnapshotRestoreService {\n\ts.indices = indices\n\treturn s\n}\n\n// IncludeGlobalState allows the global cluster state to be restored, defaults to false.\nfunc (s *SnapshotRestoreService) IncludeGlobalState(includeGlobalState bool) *SnapshotRestoreService {\n\ts.includeGlobalState = &includeGlobalState\n\treturn s\n}\n\n// RenamePattern helps rename indices on restore using regular expressions.\nfunc (s *SnapshotRestoreService) RenamePattern(renamePattern string) *SnapshotRestoreService {\n\ts.renamePattern = renamePattern\n\treturn s\n}\n\n// RenameReplacement as RenamePattern, helps rename indices on restore using regular expressions.\nfunc (s *SnapshotRestoreService) RenameReplacement(renameReplacement string) *SnapshotRestoreService {\n\ts.renameReplacement = renameReplacement\n\treturn s\n}\n\n// Partial indicates whether to restore indices that where partially snapshoted, defaults to false.\nfunc (s *SnapshotRestoreService) Partial(partial bool) *SnapshotRestoreService {\n\ts.partial = &partial\n\treturn s\n}\n\n// BodyString allows the user to specify the body of the HTTP request manually.\nfunc (s *SnapshotRestoreService) BodyString(body string) *SnapshotRestoreService {\n\ts.bodyString = body\n\treturn s\n}\n\n// IndexSettings sets the settings to be overwritten during the restore process\nfunc (s *SnapshotRestoreService) IndexSettings(indexSettings map[string]interface{}) *SnapshotRestoreService {\n\ts.indexSettings = indexSettings\n\treturn s\n}\n\n// IncludeAliases flags whether indices should be restored with their respective aliases,\n// defaults to false.\nfunc (s *SnapshotRestoreService) IncludeAliases(includeAliases bool) *SnapshotRestoreService {\n\ts.includeAliases = &includeAliases\n\treturn s\n}\n\n// IgnoreUnavailable specifies whether to ignore unavailable snapshots, defaults to false.\nfunc (s *SnapshotRestoreService) IgnoreUnavailable(ignoreUnavailable bool) *SnapshotRestoreService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// Do executes the operation.\nfunc (s *SnapshotRestoreService) Do(ctx context.Context) (*SnapshotRestoreResponse, error) {\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar body interface{}\n\tif len(s.bodyString) > 0 {\n\t\tbody = s.bodyString\n\t} else {\n\t\tbody = s.buildBody()\n\t}\n\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tret := new(SnapshotRestoreResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SnapshotRestoreService) Validate() error {\n\tvar invalid []string\n\tif s.repository == \"\" {\n\t\tinvalid = append(invalid, \"Repository\")\n\t}\n\tif s.snapshot == \"\" {\n\t\tinvalid = append(invalid, \"Snapshot\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\nfunc (s *SnapshotRestoreService) buildURL() (string, url.Values, error) {\n\tpath, err := uritemplates.Expand(\"/_snapshot/{repository}/{snapshot}/_restore\", map[string]string{\n\t\t\"snapshot\":   s.snapshot,\n\t\t\"repository\": s.repository,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif v := s.waitForCompletion; v != nil {\n\t\tparams.Set(\"wait_for_completion\", fmt.Sprint(*v))\n\t}\n\tif v := s.ignoreUnavailable; v != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\nfunc (s *SnapshotRestoreService) buildBody() interface{} {\n\tbody := map[string]interface{}{}\n\n\tif s.includeGlobalState != nil {\n\t\tbody[\"include_global_state\"] = *s.includeGlobalState\n\t}\n\tif s.partial != nil {\n\t\tbody[\"partial\"] = *s.partial\n\t}\n\tif s.includeAliases != nil {\n\t\tbody[\"include_aliases\"] = *s.includeAliases\n\t}\n\tif len(s.indices) > 0 {\n\t\tbody[\"indices\"] = strings.Join(s.indices, \",\")\n\t}\n\tif len(s.renamePattern) > 0 {\n\t\tbody[\"rename_pattern\"] = s.renamePattern\n\t}\n\tif len(s.renamePattern) > 0 {\n\t\tbody[\"rename_replacement\"] = s.renameReplacement\n\t}\n\tif len(s.indexSettings) > 0 {\n\t\tbody[\"index_settings\"] = s.indexSettings\n\t}\n\treturn body\n}\n\n// SnapshotRestoreResponse represents the response for SnapshotRestoreService.Do\ntype SnapshotRestoreResponse struct {\n\t// Accepted indicates whether the request was accepted by Elasticsearch.\n\tAccepted *bool `json:\"accepted\"`\n\n\t// Snapshot information.\n\tSnapshot *RestoreInfo `json:\"snapshot\"`\n}\n\n// RestoreInfo represents information about the restored snapshot.\ntype RestoreInfo struct {\n\tSnapshot string     `json:\"snapshot\"`\n\tIndices  []string   `json:\"indices\"`\n\tShards   ShardsInfo `json:\"shards\"`\n}\n"
  },
  {
    "path": "snapshot_restore_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"net/url\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc TestSnapshotRestoreValidate(t *testing.T) {\n\texpected := \"missing required fields: [Repository Snapshot]\"\n\tif got := NewSnapshotRestoreService(nil).Validate().Error(); got != expected {\n\t\tt.Errorf(\"expected %q; got: %q\", expected, got)\n\t}\n}\n\nfunc TestSnapshotRestorePostURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository        string\n\t\tSnapshot          string\n\t\tPretty            bool\n\t\tMasterTimeout     string\n\t\tWaitForCompletion bool\n\t\tIgnoreUnavailable bool\n\t\tExpectedPath      string\n\t\tExpectedParams    url.Values\n\t}{\n\t\t{\n\t\t\tRepository:        \"repo\",\n\t\t\tSnapshot:          \"snapshot_of_sunday\",\n\t\t\tPretty:            true,\n\t\t\tMasterTimeout:     \"60s\",\n\t\t\tWaitForCompletion: true,\n\t\t\tIgnoreUnavailable: true,\n\t\t\tExpectedPath:      \"/_snapshot/repo/snapshot_of_sunday/_restore\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"pretty\":              []string{\"true\"},\n\t\t\t\t\"master_timeout\":      []string{\"60s\"},\n\t\t\t\t\"wait_for_completion\": []string{\"true\"},\n\t\t\t\t\"ignore_unavailable\":  []string{\"true\"},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tpath, params, err := client.SnapshotRestore(tt.Repository, tt.Snapshot).\n\t\t\tPretty(tt.Pretty).\n\t\t\tMasterTimeout(tt.MasterTimeout).\n\t\t\tWaitForCompletion(tt.WaitForCompletion).\n\t\t\tIgnoreUnavailable(tt.IgnoreUnavailable).\n\t\t\tbuildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != tt.ExpectedPath {\n\t\t\tt.Errorf(\"expected Path=%q; got: %q\", tt.ExpectedPath, path)\n\t\t}\n\t\tif want, have := tt.ExpectedParams, params; !cmp.Equal(want, have) {\n\t\t\tt.Errorf(\"expected Params=%#v; got: %#v\\ndiff: %s\", want, have, cmp.Diff(want, have))\n\t\t}\n\t}\n}\n\nfunc TestSnapshotRestoreBuildBody(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository         string\n\t\tSnapshot           string\n\t\tPartial            bool\n\t\tIncludeAliases     bool\n\t\tIncludeGlobalState bool\n\t\tRenamePattern      string\n\t\tRenameReplacement  string\n\t\tIndices            []string\n\t\tIndexSettings      map[string]interface{}\n\t\tExpectedBody       map[string]interface{}\n\t}{\n\t\t{\n\t\t\tRepository:         \"repo\",\n\t\t\tSnapshot:           \"snapshot_of_sunday\",\n\t\t\tPartial:            true,\n\t\t\tIncludeAliases:     true,\n\t\t\tIncludeGlobalState: true,\n\t\t\tRenamePattern:      \"index_(.+)\",\n\t\t\tRenameReplacement:  \"restored_index_$1\",\n\t\t\tIndices:            []string{\"index_1\", \"indexe_2\", \"index_3\"},\n\t\t\tIndexSettings: map[string]interface{}{\n\t\t\t\t\"index.number_of_replicas\": 0,\n\t\t\t},\n\t\t\tExpectedBody: map[string]interface{}{\n\t\t\t\t\"partial\":              true,\n\t\t\t\t\"include_aliases\":      true,\n\t\t\t\t\"include_global_state\": true,\n\t\t\t\t\"rename_pattern\":       \"index_(.+)\",\n\t\t\t\t\"rename_replacement\":   \"restored_index_$1\",\n\t\t\t\t\"indices\":              \"index_1,indexe_2,index_3\",\n\t\t\t\t\"index_settings\": map[string]interface{}{\n\t\t\t\t\t\"index.number_of_replicas\": 0,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, tt := range tests {\n\t\tbody := client.SnapshotRestore(tt.Repository, tt.Snapshot).\n\t\t\tPartial(tt.Partial).\n\t\t\tIncludeAliases(tt.IncludeAliases).\n\t\t\tIncludeGlobalState(tt.IncludeGlobalState).\n\t\t\tRenamePattern(tt.RenamePattern).\n\t\t\tRenameReplacement(tt.RenameReplacement).\n\t\t\tIndices(tt.Indices...).\n\t\t\tIndexSettings(tt.IndexSettings).\n\t\t\tbuildBody()\n\n\t\tif want, have := tt.ExpectedBody, body; !cmp.Equal(want, have) {\n\t\t\tt.Errorf(\"expected Body=%s; got: %s\\ndiff: %s\", want, have, cmp.Diff(want, have))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "snapshot_status.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SnapshotStatusService returns information about the status of a snapshot.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.5/modules-snapshots.html\n// for details.\ntype SnapshotStatusService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository        string\n\tsnapshot          []string\n\tmasterTimeout     string\n\tignoreUnavailable *bool\n}\n\n// NewSnapshotStatusService creates a new SnapshotStatusService.\nfunc NewSnapshotStatusService(client *Client) *SnapshotStatusService {\n\treturn &SnapshotStatusService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SnapshotStatusService) Pretty(pretty bool) *SnapshotStatusService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SnapshotStatusService) Human(human bool) *SnapshotStatusService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SnapshotStatusService) ErrorTrace(errorTrace bool) *SnapshotStatusService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SnapshotStatusService) FilterPath(filterPath ...string) *SnapshotStatusService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SnapshotStatusService) Header(name string, value string) *SnapshotStatusService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SnapshotStatusService) Headers(headers http.Header) *SnapshotStatusService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository is the repository name.\nfunc (s *SnapshotStatusService) Repository(repository string) *SnapshotStatusService {\n\ts.repository = repository\n\treturn s\n}\n\n// Snapshot is the list of snapshot names. If not set, defaults to all snapshots.\nfunc (s *SnapshotStatusService) Snapshot(snapshots ...string) *SnapshotStatusService {\n\ts.snapshot = append(s.snapshot, snapshots...)\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *SnapshotStatusService) MasterTimeout(masterTimeout string) *SnapshotStatusService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SnapshotStatusService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\tif s.repository != \"\" {\n\t\tif len(s.snapshot) > 0 {\n\t\t\tpath, err = uritemplates.Expand(\"/_snapshot/{repository}/{snapshot}/_status\", map[string]string{\n\t\t\t\t\"repository\": s.repository,\n\t\t\t\t\"snapshot\":   strings.Join(s.snapshot, \",\"),\n\t\t\t})\n\t\t} else {\n\t\t\tpath, err = uritemplates.Expand(\"/_snapshot/{repository}/_status\", map[string]string{\n\t\t\t\t\"repository\": s.repository,\n\t\t\t})\n\t\t}\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/_snapshot/_status\", nil)\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif v := s.ignoreUnavailable; v != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\n//\n// Validation only fails if snapshot names were provided but no repository was\n// provided.\nfunc (s *SnapshotStatusService) Validate() error {\n\tif len(s.snapshot) > 0 && s.repository == \"\" {\n\t\treturn fmt.Errorf(\"snapshots were specified but repository is missing\")\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *SnapshotStatusService) Do(ctx context.Context) (*SnapshotStatusResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SnapshotStatusResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\ntype SnapshotStatusResponse struct {\n\tSnapshots []SnapshotStatus `json:\"snapshots\"`\n}\n\ntype SnapshotStatus struct {\n\tSnapshot           string                         `json:\"snapshot\"`\n\tRepository         string                         `json:\"repository\"`\n\tUUID               string                         `json:\"uuid\"`\n\tState              string                         `json:\"state\"`\n\tIncludeGlobalState bool                           `json:\"include_global_state\"`\n\tShardsStats        SnapshotShardsStats            `json:\"shards_stats\"`\n\tStats              SnapshotStats                  `json:\"stats\"`\n\tIndices            map[string]SnapshotIndexStatus `json:\"indices\"`\n}\n\ntype SnapshotShardsStats struct {\n\tInitializing int `json:\"initializing\"`\n\tStarted      int `json:\"started\"`\n\tFinalizing   int `json:\"finalizing\"`\n\tDone         int `json:\"done\"`\n\tFailed       int `json:\"failed\"`\n\tTotal        int `json:\"total\"`\n}\n\ntype SnapshotStats struct {\n\tIncremental struct {\n\t\tFileCount   int    `json:\"file_count\"`\n\t\tSize        string `json:\"size\"`\n\t\tSizeInBytes int64  `json:\"size_in_bytes\"`\n\t} `json:\"incremental\"`\n\n\tProcessed struct {\n\t\tFileCount   int    `json:\"file_count\"`\n\t\tSize        string `json:\"size\"`\n\t\tSizeInBytes int64  `json:\"size_in_bytes\"`\n\t} `json:\"processed\"`\n\n\tTotal struct {\n\t\tFileCount   int    `json:\"file_count\"`\n\t\tSize        string `json:\"size\"`\n\t\tSizeInBytes int64  `json:\"size_in_bytes\"`\n\t} `json:\"total\"`\n\n\tStartTime         string `json:\"start_time\"`\n\tStartTimeInMillis int64  `json:\"start_time_in_millis\"`\n\n\tTime         string `json:\"time\"`\n\tTimeInMillis int64  `json:\"time_in_millis\"`\n\n\tNumberOfFiles  int `json:\"number_of_files\"`\n\tProcessedFiles int `json:\"processed_files\"`\n\n\tTotalSize        string `json:\"total_size\"`\n\tTotalSizeInBytes int64  `json:\"total_size_in_bytes\"`\n}\n\ntype SnapshotIndexStatus struct {\n\tShardsStats SnapshotShardsStats                 `json:\"shards_stats\"`\n\tStats       SnapshotStats                       `json:\"stats\"`\n\tShards      map[string]SnapshotIndexShardStatus `json:\"shards\"`\n}\n\ntype SnapshotIndexShardStatus struct {\n\tStage  string        `json:\"stage\"` // initializing, started, finalize, done, or failed\n\tStats  SnapshotStats `json:\"stats\"`\n\tNode   string        `json:\"node\"`\n\tReason string        `json:\"reason\"` // reason for failure\n}\n"
  },
  {
    "path": "snapshot_status_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"net/url\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestSnapshotStatusURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository     string\n\t\tSnapshot       []string\n\t\tMasterTimeout  string\n\t\tExpectedPath   string\n\t\tExpectedParams url.Values\n\t}{\n\t\t{\n\t\t\tRepository:    \"repo\",\n\t\t\tSnapshot:      []string{},\n\t\t\tMasterTimeout: \"60s\",\n\t\t\tExpectedPath:  \"/_snapshot/repo/_status\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"master_timeout\": []string{\"60s\"},\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tRepository:    \"repo\",\n\t\t\tSnapshot:      []string{\"snapA\", \"snapB\"},\n\t\t\tMasterTimeout: \"30s\",\n\t\t\tExpectedPath:  \"/_snapshot/repo/snapA%2CsnapB/_status\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"master_timeout\": []string{\"30s\"},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, params, err := client.SnapshotStatus().\n\t\t\tMasterTimeout(test.MasterTimeout).\n\t\t\tRepository(test.Repository).\n\t\t\tSnapshot(test.Snapshot...).\n\t\t\tbuildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.ExpectedPath {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.ExpectedPath, path)\n\t\t}\n\t\tif !reflect.DeepEqual(params, test.ExpectedParams) {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.ExpectedParams, params)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "snapshot_verify_repository.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// SnapshotVerifyRepositoryService verifies a snapshop repository.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-snapshots.html\n// for details.\ntype SnapshotVerifyRepositoryService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\trepository    string\n\tmasterTimeout string\n\ttimeout       string\n}\n\n// NewSnapshotVerifyRepositoryService creates a new SnapshotVerifyRepositoryService.\nfunc NewSnapshotVerifyRepositoryService(client *Client) *SnapshotVerifyRepositoryService {\n\treturn &SnapshotVerifyRepositoryService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *SnapshotVerifyRepositoryService) Pretty(pretty bool) *SnapshotVerifyRepositoryService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *SnapshotVerifyRepositoryService) Human(human bool) *SnapshotVerifyRepositoryService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *SnapshotVerifyRepositoryService) ErrorTrace(errorTrace bool) *SnapshotVerifyRepositoryService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *SnapshotVerifyRepositoryService) FilterPath(filterPath ...string) *SnapshotVerifyRepositoryService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *SnapshotVerifyRepositoryService) Header(name string, value string) *SnapshotVerifyRepositoryService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *SnapshotVerifyRepositoryService) Headers(headers http.Header) *SnapshotVerifyRepositoryService {\n\ts.headers = headers\n\treturn s\n}\n\n// Repository specifies the repository name.\nfunc (s *SnapshotVerifyRepositoryService) Repository(repository string) *SnapshotVerifyRepositoryService {\n\ts.repository = repository\n\treturn s\n}\n\n// MasterTimeout is the explicit operation timeout for connection to master node.\nfunc (s *SnapshotVerifyRepositoryService) MasterTimeout(masterTimeout string) *SnapshotVerifyRepositoryService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *SnapshotVerifyRepositoryService) Timeout(timeout string) *SnapshotVerifyRepositoryService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *SnapshotVerifyRepositoryService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_snapshot/{repository}/_verify\", map[string]string{\n\t\t\"repository\": s.repository,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *SnapshotVerifyRepositoryService) Validate() error {\n\tvar invalid []string\n\tif s.repository == \"\" {\n\t\tinvalid = append(invalid, \"Repository\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *SnapshotVerifyRepositoryService) Do(ctx context.Context) (*SnapshotVerifyRepositoryResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(SnapshotVerifyRepositoryResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// SnapshotVerifyRepositoryResponse is the response of SnapshotVerifyRepositoryService.Do.\ntype SnapshotVerifyRepositoryResponse struct {\n\tNodes map[string]*SnapshotVerifyRepositoryNode `json:\"nodes\"`\n}\n\ntype SnapshotVerifyRepositoryNode struct {\n\tName string `json:\"name\"`\n}\n"
  },
  {
    "path": "snapshot_verify_repository_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestSnapshotVerifyRepositoryURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tRepository string\n\t\tExpected   string\n\t}{\n\t\t{\n\t\t\t\"repo\",\n\t\t\t\"/_snapshot/repo/_verify\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tpath, _, err := client.SnapshotVerifyRepository(test.Repository).buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "sort.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"errors\"\n\n// -- Sorter --\n\n// Sorter is an interface for sorting strategies, e.g. ScoreSort or FieldSort.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-sort.html.\ntype Sorter interface {\n\tSource() (interface{}, error)\n}\n\n// -- SortInfo --\n\n// SortInfo contains information about sorting a field.\ntype SortInfo struct {\n\tSorter\n\tField          string\n\tAscending      bool\n\tMissing        interface{}\n\tIgnoreUnmapped *bool\n\tUnmappedType   string\n\tSortMode       string\n\tNestedFilter   Query // deprecated in 6.1 and replaced by Filter\n\tFilter         Query\n\tNestedPath     string // deprecated in 6.1 and replaced by Path\n\tPath           string\n\tNestedSort     *NestedSort // deprecated in 6.1 and replaced by Nested\n\tNested         *NestedSort\n}\n\nfunc (info SortInfo) Source() (interface{}, error) {\n\tprop := make(map[string]interface{})\n\tif info.Ascending {\n\t\tprop[\"order\"] = \"asc\"\n\t} else {\n\t\tprop[\"order\"] = \"desc\"\n\t}\n\tif info.Missing != nil {\n\t\tprop[\"missing\"] = info.Missing\n\t}\n\tif info.IgnoreUnmapped != nil {\n\t\tprop[\"ignore_unmapped\"] = *info.IgnoreUnmapped\n\t}\n\tif info.UnmappedType != \"\" {\n\t\tprop[\"unmapped_type\"] = info.UnmappedType\n\t}\n\tif info.SortMode != \"\" {\n\t\tprop[\"mode\"] = info.SortMode\n\t}\n\tif info.Filter != nil {\n\t\tsrc, err := info.Filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tprop[\"filter\"] = src\n\t} else if info.NestedFilter != nil {\n\t\tsrc, err := info.NestedFilter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tprop[\"nested_filter\"] = src // deprecated in 6.1\n\t}\n\tif info.Path != \"\" {\n\t\tprop[\"path\"] = info.Path\n\t} else if info.NestedPath != \"\" {\n\t\tprop[\"nested_path\"] = info.NestedPath // deprecated in 6.1\n\t}\n\tif info.Nested != nil {\n\t\tsrc, err := info.Nested.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tprop[\"nested\"] = src\n\t} else if info.NestedSort != nil {\n\t\tsrc, err := info.NestedSort.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tprop[\"nested\"] = src\n\t}\n\tsource := make(map[string]interface{})\n\tsource[info.Field] = prop\n\treturn source, nil\n}\n\n// -- SortByDoc --\n\n// SortByDoc sorts by the \"_doc\" field, as described in\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-scroll.html.\n//\n// Example:\n//   ss := elastic.NewSearchSource()\n//   ss = ss.SortBy(elastic.SortByDoc{})\ntype SortByDoc struct {\n\tSorter\n}\n\n// Source returns the JSON-serializable data.\nfunc (s SortByDoc) Source() (interface{}, error) {\n\treturn \"_doc\", nil\n}\n\n// -- ScoreSort --\n\n// ScoreSort sorts by relevancy score.\ntype ScoreSort struct {\n\tSorter\n\tascending bool\n}\n\n// NewScoreSort creates a new ScoreSort.\nfunc NewScoreSort() *ScoreSort {\n\treturn &ScoreSort{ascending: false} // Descending by default!\n}\n\n// Order defines whether sorting ascending (default) or descending.\nfunc (s *ScoreSort) Order(ascending bool) *ScoreSort {\n\ts.ascending = ascending\n\treturn s\n}\n\n// Asc sets ascending sort order.\nfunc (s *ScoreSort) Asc() *ScoreSort {\n\ts.ascending = true\n\treturn s\n}\n\n// Desc sets descending sort order.\nfunc (s *ScoreSort) Desc() *ScoreSort {\n\ts.ascending = false\n\treturn s\n}\n\n// Source returns the JSON-serializable data.\nfunc (s *ScoreSort) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tx := make(map[string]interface{})\n\tsource[\"_score\"] = x\n\tif s.ascending {\n\t\tx[\"order\"] = \"asc\"\n\t} else {\n\t\tx[\"order\"] = \"desc\"\n\t}\n\treturn source, nil\n}\n\n// -- FieldSort --\n\n// FieldSort sorts by a given field.\ntype FieldSort struct {\n\tSorter\n\tfieldName    string\n\tascending    bool\n\tmissing      interface{}\n\tunmappedType *string\n\tsortMode     *string\n\tfilter       Query\n\tpath         *string\n\tnested       *NestedSort\n}\n\n// NewFieldSort creates a new FieldSort.\nfunc NewFieldSort(fieldName string) *FieldSort {\n\treturn &FieldSort{\n\t\tfieldName: fieldName,\n\t\tascending: true,\n\t}\n}\n\n// FieldName specifies the name of the field to be used for sorting.\nfunc (s *FieldSort) FieldName(fieldName string) *FieldSort {\n\ts.fieldName = fieldName\n\treturn s\n}\n\n// Order defines whether sorting ascending (default) or descending.\nfunc (s *FieldSort) Order(ascending bool) *FieldSort {\n\ts.ascending = ascending\n\treturn s\n}\n\n// Asc sets ascending sort order.\nfunc (s *FieldSort) Asc() *FieldSort {\n\ts.ascending = true\n\treturn s\n}\n\n// Desc sets descending sort order.\nfunc (s *FieldSort) Desc() *FieldSort {\n\ts.ascending = false\n\treturn s\n}\n\n// Missing sets the value to be used when a field is missing in a document.\n// You can also use \"_last\" or \"_first\" to sort missing last or first\n// respectively.\nfunc (s *FieldSort) Missing(missing interface{}) *FieldSort {\n\ts.missing = missing\n\treturn s\n}\n\n// UnmappedType sets the type to use when the current field is not mapped\n// in an index.\nfunc (s *FieldSort) UnmappedType(typ string) *FieldSort {\n\ts.unmappedType = &typ\n\treturn s\n}\n\n// SortMode specifies what values to pick in case a document contains\n// multiple values for the targeted sort field. Possible values are:\n// min, max, sum, and avg.\nfunc (s *FieldSort) SortMode(sortMode string) *FieldSort {\n\ts.sortMode = &sortMode\n\treturn s\n}\n\n// NestedFilter sets a filter that nested objects should match with\n// in order to be taken into account for sorting.\n// Deprecated: Use Filter instead.\nfunc (s *FieldSort) NestedFilter(nestedFilter Query) *FieldSort {\n\ts.filter = nestedFilter\n\treturn s\n}\n\n// Filter sets a filter that nested objects should match with\n// in order to be taken into account for sorting.\nfunc (s *FieldSort) Filter(filter Query) *FieldSort {\n\ts.filter = filter\n\treturn s\n}\n\n// NestedPath is used if sorting occurs on a field that is inside a\n// nested object.\n// Deprecated: Use Path instead.\nfunc (s *FieldSort) NestedPath(nestedPath string) *FieldSort {\n\ts.path = &nestedPath\n\treturn s\n}\n\n// Path is used if sorting occurs on a field that is inside a\n// nested object.\nfunc (s *FieldSort) Path(path string) *FieldSort {\n\ts.path = &path\n\treturn s\n}\n\n// NestedSort is available starting with 6.1 and will replace NestedFilter\n// and NestedPath.\n// Deprecated: Use Nested instead.\nfunc (s *FieldSort) NestedSort(nestedSort *NestedSort) *FieldSort {\n\ts.nested = nestedSort\n\treturn s\n}\n\n// Nested is available starting with 6.1 and will replace Filter and Path.\nfunc (s *FieldSort) Nested(nested *NestedSort) *FieldSort {\n\ts.nested = nested\n\treturn s\n}\n\n// Source returns the JSON-serializable data.\nfunc (s *FieldSort) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tx := make(map[string]interface{})\n\tsource[s.fieldName] = x\n\tif s.ascending {\n\t\tx[\"order\"] = \"asc\"\n\t} else {\n\t\tx[\"order\"] = \"desc\"\n\t}\n\tif s.missing != nil {\n\t\tx[\"missing\"] = s.missing\n\t}\n\tif s.unmappedType != nil {\n\t\tx[\"unmapped_type\"] = *s.unmappedType\n\t}\n\tif s.sortMode != nil {\n\t\tx[\"mode\"] = *s.sortMode\n\t}\n\tif s.filter != nil {\n\t\tsrc, err := s.filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tx[\"filter\"] = src\n\t}\n\tif s.path != nil {\n\t\tx[\"path\"] = *s.path\n\t}\n\tif s.nested != nil {\n\t\tsrc, err := s.nested.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tx[\"nested\"] = src\n\t}\n\treturn source, nil\n}\n\n// -- GeoDistanceSort --\n\n// GeoDistanceSort allows for sorting by geographic distance.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-sort.html#_geo_distance_sorting.\ntype GeoDistanceSort struct {\n\tSorter\n\tfieldName      string\n\tpoints         []*GeoPoint\n\tgeohashes      []string\n\tdistanceType   *string\n\tunit           string\n\tignoreUnmapped *bool\n\tascending      bool\n\tsortMode       *string\n\tnestedFilter   Query\n\tnestedPath     *string\n\tnestedSort     *NestedSort\n}\n\n// NewGeoDistanceSort creates a new sorter for geo distances.\nfunc NewGeoDistanceSort(fieldName string) *GeoDistanceSort {\n\treturn &GeoDistanceSort{\n\t\tfieldName: fieldName,\n\t\tascending: true,\n\t}\n}\n\n// FieldName specifies the name of the (geo) field to use for sorting.\nfunc (s *GeoDistanceSort) FieldName(fieldName string) *GeoDistanceSort {\n\ts.fieldName = fieldName\n\treturn s\n}\n\n// Order defines whether sorting ascending (default) or descending.\nfunc (s *GeoDistanceSort) Order(ascending bool) *GeoDistanceSort {\n\ts.ascending = ascending\n\treturn s\n}\n\n// Asc sets ascending sort order.\nfunc (s *GeoDistanceSort) Asc() *GeoDistanceSort {\n\ts.ascending = true\n\treturn s\n}\n\n// Desc sets descending sort order.\nfunc (s *GeoDistanceSort) Desc() *GeoDistanceSort {\n\ts.ascending = false\n\treturn s\n}\n\n// Point specifies a point to create the range distance aggregations from.\nfunc (s *GeoDistanceSort) Point(lat, lon float64) *GeoDistanceSort {\n\ts.points = append(s.points, GeoPointFromLatLon(lat, lon))\n\treturn s\n}\n\n// Points specifies the geo point(s) to create the range distance aggregations from.\nfunc (s *GeoDistanceSort) Points(points ...*GeoPoint) *GeoDistanceSort {\n\ts.points = append(s.points, points...)\n\treturn s\n}\n\n// GeoHashes specifies the geo point to create the range distance aggregations from.\nfunc (s *GeoDistanceSort) GeoHashes(geohashes ...string) *GeoDistanceSort {\n\ts.geohashes = append(s.geohashes, geohashes...)\n\treturn s\n}\n\n// Unit specifies the distance unit to use. It defaults to km.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/common-options.html#distance-units\n// for details.\nfunc (s *GeoDistanceSort) Unit(unit string) *GeoDistanceSort {\n\ts.unit = unit\n\treturn s\n}\n\n// IgnoreUnmapped indicates whether the unmapped field should be treated as\n// a missing value. Setting it to true is equivalent to specifying an\n// unmapped_type in the field sort. The default is false (unmapped field\n// causes the search to fail).\nfunc (s *GeoDistanceSort) IgnoreUnmapped(ignoreUnmapped bool) *GeoDistanceSort {\n\ts.ignoreUnmapped = &ignoreUnmapped\n\treturn s\n}\n\n// GeoDistance is an alias for DistanceType.\nfunc (s *GeoDistanceSort) GeoDistance(geoDistance string) *GeoDistanceSort {\n\treturn s.DistanceType(geoDistance)\n}\n\n// DistanceType describes how to compute the distance, e.g. \"arc\" or \"plane\".\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-sort.html#geo-sorting\n// for details.\nfunc (s *GeoDistanceSort) DistanceType(distanceType string) *GeoDistanceSort {\n\ts.distanceType = &distanceType\n\treturn s\n}\n\n// SortMode specifies what values to pick in case a document contains\n// multiple values for the targeted sort field. Possible values are:\n// min, max, sum, and avg.\nfunc (s *GeoDistanceSort) SortMode(sortMode string) *GeoDistanceSort {\n\ts.sortMode = &sortMode\n\treturn s\n}\n\n// NestedFilter sets a filter that nested objects should match with\n// in order to be taken into account for sorting.\nfunc (s *GeoDistanceSort) NestedFilter(nestedFilter Query) *GeoDistanceSort {\n\ts.nestedFilter = nestedFilter\n\treturn s\n}\n\n// NestedPath is used if sorting occurs on a field that is inside a\n// nested object.\nfunc (s *GeoDistanceSort) NestedPath(nestedPath string) *GeoDistanceSort {\n\ts.nestedPath = &nestedPath\n\treturn s\n}\n\n// NestedSort is available starting with 6.1 and will replace NestedFilter\n// and NestedPath.\nfunc (s *GeoDistanceSort) NestedSort(nestedSort *NestedSort) *GeoDistanceSort {\n\ts.nestedSort = nestedSort\n\treturn s\n}\n\n// Source returns the JSON-serializable data.\nfunc (s *GeoDistanceSort) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tx := make(map[string]interface{})\n\tsource[\"_geo_distance\"] = x\n\n\t// Points\n\tvar ptarr []interface{}\n\tfor _, pt := range s.points {\n\t\tptarr = append(ptarr, pt.Source())\n\t}\n\tfor _, geohash := range s.geohashes {\n\t\tptarr = append(ptarr, geohash)\n\t}\n\tx[s.fieldName] = ptarr\n\n\tif s.unit != \"\" {\n\t\tx[\"unit\"] = s.unit\n\t}\n\tif s.ignoreUnmapped != nil {\n\t\tx[\"ignore_unmapped\"] = *s.ignoreUnmapped\n\t}\n\tif s.distanceType != nil {\n\t\tx[\"distance_type\"] = *s.distanceType\n\t}\n\n\tif s.ascending {\n\t\tx[\"order\"] = \"asc\"\n\t} else {\n\t\tx[\"order\"] = \"desc\"\n\t}\n\tif s.sortMode != nil {\n\t\tx[\"mode\"] = *s.sortMode\n\t}\n\tif s.nestedFilter != nil {\n\t\tsrc, err := s.nestedFilter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tx[\"nested_filter\"] = src\n\t}\n\tif s.nestedPath != nil {\n\t\tx[\"nested_path\"] = *s.nestedPath\n\t}\n\tif s.nestedSort != nil {\n\t\tsrc, err := s.nestedSort.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tx[\"nested\"] = src\n\t}\n\treturn source, nil\n}\n\n// -- ScriptSort --\n\n// ScriptSort sorts by a custom script. See\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/modules-scripting.html#modules-scripting\n// for details about scripting.\ntype ScriptSort struct {\n\tSorter\n\tscript       *Script\n\ttyp          string\n\tascending    bool\n\tsortMode     *string\n\tnestedFilter Query\n\tnestedPath   *string\n\tnestedSort   *NestedSort\n}\n\n// NewScriptSort creates and initializes a new ScriptSort.\n// You must provide a script and a type, e.g. \"string\" or \"number\".\nfunc NewScriptSort(script *Script, typ string) *ScriptSort {\n\treturn &ScriptSort{\n\t\tscript:    script,\n\t\ttyp:       typ,\n\t\tascending: true,\n\t}\n}\n\n// Type sets the script type, which can be either \"string\" or \"number\".\nfunc (s *ScriptSort) Type(typ string) *ScriptSort {\n\ts.typ = typ\n\treturn s\n}\n\n// Order defines whether sorting ascending (default) or descending.\nfunc (s *ScriptSort) Order(ascending bool) *ScriptSort {\n\ts.ascending = ascending\n\treturn s\n}\n\n// Asc sets ascending sort order.\nfunc (s *ScriptSort) Asc() *ScriptSort {\n\ts.ascending = true\n\treturn s\n}\n\n// Desc sets descending sort order.\nfunc (s *ScriptSort) Desc() *ScriptSort {\n\ts.ascending = false\n\treturn s\n}\n\n// SortMode specifies what values to pick in case a document contains\n// multiple values for the targeted sort field. Possible values are:\n// min or max.\nfunc (s *ScriptSort) SortMode(sortMode string) *ScriptSort {\n\ts.sortMode = &sortMode\n\treturn s\n}\n\n// NestedFilter sets a filter that nested objects should match with\n// in order to be taken into account for sorting.\nfunc (s *ScriptSort) NestedFilter(nestedFilter Query) *ScriptSort {\n\ts.nestedFilter = nestedFilter\n\treturn s\n}\n\n// NestedPath is used if sorting occurs on a field that is inside a\n// nested object.\nfunc (s *ScriptSort) NestedPath(nestedPath string) *ScriptSort {\n\ts.nestedPath = &nestedPath\n\treturn s\n}\n\n// NestedSort is available starting with 6.1 and will replace NestedFilter\n// and NestedPath.\nfunc (s *ScriptSort) NestedSort(nestedSort *NestedSort) *ScriptSort {\n\ts.nestedSort = nestedSort\n\treturn s\n}\n\n// Source returns the JSON-serializable data.\nfunc (s *ScriptSort) Source() (interface{}, error) {\n\tif s.script == nil {\n\t\treturn nil, errors.New(\"ScriptSort expected a script\")\n\t}\n\tsource := make(map[string]interface{})\n\tx := make(map[string]interface{})\n\tsource[\"_script\"] = x\n\n\tsrc, err := s.script.Source()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tx[\"script\"] = src\n\n\tx[\"type\"] = s.typ\n\n\tif s.ascending {\n\t\tx[\"order\"] = \"asc\"\n\t} else {\n\t\tx[\"order\"] = \"desc\"\n\t}\n\tif s.sortMode != nil {\n\t\tx[\"mode\"] = *s.sortMode\n\t}\n\tif s.nestedFilter != nil {\n\t\tsrc, err := s.nestedFilter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tx[\"nested_filter\"] = src\n\t}\n\tif s.nestedPath != nil {\n\t\tx[\"nested_path\"] = *s.nestedPath\n\t}\n\tif s.nestedSort != nil {\n\t\tsrc, err := s.nestedSort.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tx[\"nested\"] = src\n\t}\n\treturn source, nil\n}\n\n// -- NestedSort --\n\n// NestedSort is used for fields that are inside a nested object.\n// It takes a \"path\" argument and an optional nested filter that the\n// nested objects should match with in order to be taken into account\n// for sorting.\n//\n// NestedSort is available from 6.1 and replaces nestedFilter and nestedPath\n// in the other sorters.\ntype NestedSort struct {\n\tSorter\n\tpath       string\n\tfilter     Query\n\tnestedSort *NestedSort\n}\n\n// NewNestedSort creates a new NestedSort.\nfunc NewNestedSort(path string) *NestedSort {\n\treturn &NestedSort{path: path}\n}\n\n// Filter sets the filter.\nfunc (s *NestedSort) Filter(filter Query) *NestedSort {\n\ts.filter = filter\n\treturn s\n}\n\n// NestedSort embeds another level of nested sorting.\nfunc (s *NestedSort) NestedSort(nestedSort *NestedSort) *NestedSort {\n\ts.nestedSort = nestedSort\n\treturn s\n}\n\n// Source returns the JSON-serializable data.\nfunc (s *NestedSort) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tif s.path != \"\" {\n\t\tsource[\"path\"] = s.path\n\t}\n\tif s.filter != nil {\n\t\tsrc, err := s.filter.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"filter\"] = src\n\t}\n\tif s.nestedSort != nil {\n\t\tsrc, err := s.nestedSort.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"nested\"] = src\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "sort_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSortInfo(t *testing.T) {\n\tbuilder := SortInfo{Field: \"grade\", Ascending: false}\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"grade\":{\"order\":\"desc\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSortInfoComplex(t *testing.T) {\n\tbuilder := SortInfo{\n\t\tField:     \"price\",\n\t\tAscending: false,\n\t\tMissing:   \"_last\",\n\t\tSortMode:  \"avg\",\n\t\tFilter:    NewTermQuery(\"product.color\", \"blue\"),\n\t\tPath:      \"variant\",\n\t}\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"price\":{\"filter\":{\"term\":{\"product.color\":\"blue\"}},\"missing\":\"_last\",\"mode\":\"avg\",\"order\":\"desc\",\"path\":\"variant\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScoreSort(t *testing.T) {\n\tbuilder := NewScoreSort()\n\tif builder.ascending != false {\n\t\tt.Error(\"expected score sorter to be ascending by default\")\n\t}\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_score\":{\"order\":\"desc\"}}` // ScoreSort is \"desc\" by default\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScoreSortOrderAscending(t *testing.T) {\n\tbuilder := NewScoreSort().Asc()\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_score\":{\"order\":\"asc\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScoreSortOrderDescending(t *testing.T) {\n\tbuilder := NewScoreSort().Desc()\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_score\":{\"order\":\"desc\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFieldSort(t *testing.T) {\n\tbuilder := NewFieldSort(\"grade\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"grade\":{\"order\":\"asc\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFieldSortOrderDesc(t *testing.T) {\n\tbuilder := NewFieldSort(\"grade\").Desc()\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"grade\":{\"order\":\"desc\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFieldSortComplex(t *testing.T) {\n\tbuilder := NewFieldSort(\"price\").Desc().\n\t\tSortMode(\"avg\").\n\t\tMissing(\"_last\").\n\t\tUnmappedType(\"product\").\n\t\tFilter(NewTermQuery(\"product.color\", \"blue\")).\n\t\tPath(\"variant\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"price\":{\"filter\":{\"term\":{\"product.color\":\"blue\"}},\"missing\":\"_last\",\"mode\":\"avg\",\"order\":\"desc\",\"path\":\"variant\",\"unmapped_type\":\"product\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoDistanceSort(t *testing.T) {\n\tbuilder := NewGeoDistanceSort(\"pin.location\").\n\t\tPoint(-70, 40).\n\t\tOrder(true).\n\t\tUnit(\"km\").\n\t\tIgnoreUnmapped(true).\n\t\tSortMode(\"min\").\n\t\tGeoDistance(\"plane\")\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_geo_distance\":{\"distance_type\":\"plane\",\"ignore_unmapped\":true,\"mode\":\"min\",\"order\":\"asc\",\"pin.location\":[{\"lat\":-70,\"lon\":40}],\"unit\":\"km\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestGeoDistanceSortOrderDesc(t *testing.T) {\n\tbuilder := NewGeoDistanceSort(\"pin.location\").\n\t\tPoint(-70, 40).\n\t\tUnit(\"km\").\n\t\tSortMode(\"min\").\n\t\tGeoDistance(\"arc\").\n\t\tDesc()\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_geo_distance\":{\"distance_type\":\"arc\",\"mode\":\"min\",\"order\":\"desc\",\"pin.location\":[{\"lat\":-70,\"lon\":40}],\"unit\":\"km\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\nfunc TestScriptSort(t *testing.T) {\n\tbuilder := NewScriptSort(NewScript(\"doc['field_name'].value * factor\").Param(\"factor\", 1.1), \"number\").Order(true)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_script\":{\"order\":\"asc\",\"script\":{\"params\":{\"factor\":1.1},\"source\":\"doc['field_name'].value * factor\"},\"type\":\"number\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestScriptSortOrderDesc(t *testing.T) {\n\tbuilder := NewScriptSort(NewScript(\"doc['field_name'].value * factor\").Param(\"factor\", 1.1), \"number\").Desc()\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_script\":{\"order\":\"desc\",\"script\":{\"params\":{\"factor\":1.1},\"source\":\"doc['field_name'].value * factor\"},\"type\":\"number\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestNestedSort(t *testing.T) {\n\tbuilder := NewNestedSort(\"offer\").\n\t\tFilter(NewTermQuery(\"offer.color\", \"blue\"))\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"filter\":{\"term\":{\"offer.color\":\"blue\"}},\"path\":\"offer\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestFieldSortWithNestedSort(t *testing.T) {\n\tbuilder := NewFieldSort(\"offer.price\").\n\t\tAsc().\n\t\tSortMode(\"avg\").\n\t\tNestedSort(\n\t\t\tNewNestedSort(\"offer\").Filter(NewTermQuery(\"offer.color\", \"blue\")),\n\t\t)\n\tsrc, err := builder.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"offer.price\":{\"mode\":\"avg\",\"nested\":{\"filter\":{\"term\":{\"offer.color\":\"blue\"}},\"path\":\"offer\"},\"order\":\"asc\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "suggest_field.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n)\n\n// SuggestField can be used by the caller to specify a suggest field\n// at index time. For a detailed example, see e.g.\n// https://www.elastic.co/blog/you-complete-me.\ntype SuggestField struct {\n\tinputs         []string\n\tweight         int\n\tcontextQueries []SuggesterContextQuery\n}\n\nfunc NewSuggestField(input ...string) *SuggestField {\n\treturn &SuggestField{\n\t\tinputs: input,\n\t\tweight: -1,\n\t}\n}\n\nfunc (f *SuggestField) Input(input ...string) *SuggestField {\n\tif f.inputs == nil {\n\t\tf.inputs = make([]string, 0)\n\t}\n\tf.inputs = append(f.inputs, input...)\n\treturn f\n}\n\nfunc (f *SuggestField) Weight(weight int) *SuggestField {\n\tf.weight = weight\n\treturn f\n}\n\nfunc (f *SuggestField) ContextQuery(queries ...SuggesterContextQuery) *SuggestField {\n\tf.contextQueries = append(f.contextQueries, queries...)\n\treturn f\n}\n\n// MarshalJSON encodes SuggestField into JSON.\nfunc (f *SuggestField) MarshalJSON() ([]byte, error) {\n\tsource := make(map[string]interface{})\n\n\tif f.inputs != nil {\n\t\tswitch len(f.inputs) {\n\t\tcase 1:\n\t\t\tsource[\"input\"] = f.inputs[0]\n\t\tdefault:\n\t\t\tsource[\"input\"] = f.inputs\n\t\t}\n\t}\n\n\tif f.weight >= 0 {\n\t\tsource[\"weight\"] = f.weight\n\t}\n\n\tswitch len(f.contextQueries) {\n\tcase 0:\n\tcase 1:\n\t\tsrc, err := f.contextQueries[0].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"contexts\"] = src\n\tdefault:\n\t\tctxq := make(map[string]interface{})\n\t\tfor _, query := range f.contextQueries {\n\t\t\tsrc, err := query.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tm, ok := src.(map[string]interface{})\n\t\t\tif !ok {\n\t\t\t\treturn nil, errors.New(\"SuggesterContextQuery must be of type map[string]interface{}\")\n\t\t\t}\n\t\t\tfor k, v := range m {\n\t\t\t\tctxq[k] = v\n\t\t\t}\n\t\t}\n\t\tsource[\"contexts\"] = ctxq\n\t}\n\n\treturn json.Marshal(source)\n}\n"
  },
  {
    "path": "suggest_field_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSuggestField(t *testing.T) {\n\tfield := NewSuggestField().\n\t\tInput(\"Welcome to Golang and Elasticsearch.\", \"Golang and Elasticsearch\").\n\t\tWeight(1).\n\t\tContextQuery(\n\t\t\tNewSuggesterCategoryMapping(\"color\").FieldName(\"color_field\").DefaultValues(\"red\", \"green\", \"blue\"),\n\t\t\tNewSuggesterGeoMapping(\"location\").Precision(\"5m\").Neighbors(true).DefaultLocations(GeoPointFromLatLon(52.516275, 13.377704)),\n\t\t)\n\tdata, err := json.Marshal(field)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"contexts\":{\"color\":{\"default\":[\"red\",\"green\",\"blue\"],\"path\":\"color_field\",\"type\":\"category\"},\"location\":{\"default\":{\"lat\":52.516275,\"lon\":13.377704},\"neighbors\":true,\"precision\":[\"5m\"],\"type\":\"geo\"}},\"input\":[\"Welcome to Golang and Elasticsearch.\",\"Golang and Elasticsearch\"],\"weight\":1}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "suggester.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// Represents the generic suggester interface.\n// A suggester's only purpose is to return the\n// source of the query as a JSON-serializable\n// object. Returning a map[string]interface{}\n// will do.\ntype Suggester interface {\n\tName() string\n\tSource(includeName bool) (interface{}, error)\n}\n"
  },
  {
    "path": "suggester_completion.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"errors\"\n\n// CompletionSuggester is a fast suggester for e.g. type-ahead completion.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-completion.html\n// for more details.\ntype CompletionSuggester struct {\n\tSuggester\n\tname           string\n\ttext           string\n\tprefix         string\n\tregex          string\n\tfield          string\n\tanalyzer       string\n\tsize           *int\n\tshardSize      *int\n\tcontextQueries []SuggesterContextQuery\n\n\tfuzzyOptions   *FuzzyCompletionSuggesterOptions\n\tregexOptions   *RegexCompletionSuggesterOptions\n\tskipDuplicates *bool\n}\n\n// Creates a new completion suggester.\nfunc NewCompletionSuggester(name string) *CompletionSuggester {\n\treturn &CompletionSuggester{\n\t\tname: name,\n\t}\n}\n\nfunc (q *CompletionSuggester) Name() string {\n\treturn q.name\n}\n\nfunc (q *CompletionSuggester) Text(text string) *CompletionSuggester {\n\tq.text = text\n\treturn q\n}\n\nfunc (q *CompletionSuggester) Prefix(prefix string) *CompletionSuggester {\n\tq.prefix = prefix\n\treturn q\n}\n\nfunc (q *CompletionSuggester) PrefixWithEditDistance(prefix string, editDistance interface{}) *CompletionSuggester {\n\tq.prefix = prefix\n\tq.fuzzyOptions = NewFuzzyCompletionSuggesterOptions().EditDistance(editDistance)\n\treturn q\n}\n\nfunc (q *CompletionSuggester) PrefixWithOptions(prefix string, options *FuzzyCompletionSuggesterOptions) *CompletionSuggester {\n\tq.prefix = prefix\n\tq.fuzzyOptions = options\n\treturn q\n}\n\nfunc (q *CompletionSuggester) FuzzyOptions(options *FuzzyCompletionSuggesterOptions) *CompletionSuggester {\n\tq.fuzzyOptions = options\n\treturn q\n}\n\nfunc (q *CompletionSuggester) Fuzziness(fuzziness interface{}) *CompletionSuggester {\n\tif q.fuzzyOptions == nil {\n\t\tq.fuzzyOptions = NewFuzzyCompletionSuggesterOptions()\n\t}\n\tq.fuzzyOptions = q.fuzzyOptions.EditDistance(fuzziness)\n\treturn q\n}\n\nfunc (q *CompletionSuggester) Regex(regex string) *CompletionSuggester {\n\tq.regex = regex\n\treturn q\n}\n\nfunc (q *CompletionSuggester) RegexWithOptions(regex string, options *RegexCompletionSuggesterOptions) *CompletionSuggester {\n\tq.regex = regex\n\tq.regexOptions = options\n\treturn q\n}\n\nfunc (q *CompletionSuggester) RegexOptions(options *RegexCompletionSuggesterOptions) *CompletionSuggester {\n\tq.regexOptions = options\n\treturn q\n}\n\nfunc (q *CompletionSuggester) SkipDuplicates(skipDuplicates bool) *CompletionSuggester {\n\tq.skipDuplicates = &skipDuplicates\n\treturn q\n}\n\nfunc (q *CompletionSuggester) Field(field string) *CompletionSuggester {\n\tq.field = field\n\treturn q\n}\n\nfunc (q *CompletionSuggester) Analyzer(analyzer string) *CompletionSuggester {\n\tq.analyzer = analyzer\n\treturn q\n}\n\nfunc (q *CompletionSuggester) Size(size int) *CompletionSuggester {\n\tq.size = &size\n\treturn q\n}\n\nfunc (q *CompletionSuggester) ShardSize(shardSize int) *CompletionSuggester {\n\tq.shardSize = &shardSize\n\treturn q\n}\n\nfunc (q *CompletionSuggester) ContextQuery(query SuggesterContextQuery) *CompletionSuggester {\n\tq.contextQueries = append(q.contextQueries, query)\n\treturn q\n}\n\nfunc (q *CompletionSuggester) ContextQueries(queries ...SuggesterContextQuery) *CompletionSuggester {\n\tq.contextQueries = append(q.contextQueries, queries...)\n\treturn q\n}\n\n// completionSuggesterRequest is necessary because the order in which\n// the JSON elements are routed to Elasticsearch is relevant.\n// We got into trouble when using plain maps because the text element\n// needs to go before the completion element.\ntype completionSuggesterRequest struct {\n\tText       string      `json:\"text,omitempty\"`\n\tPrefix     string      `json:\"prefix,omitempty\"`\n\tRegex      string      `json:\"regex,omitempty\"`\n\tCompletion interface{} `json:\"completion,omitempty\"`\n}\n\n// Source creates the JSON data for the completion suggester.\nfunc (q *CompletionSuggester) Source(includeName bool) (interface{}, error) {\n\tcs := &completionSuggesterRequest{}\n\n\tif q.text != \"\" {\n\t\tcs.Text = q.text\n\t}\n\tif q.prefix != \"\" {\n\t\tcs.Prefix = q.prefix\n\t}\n\tif q.regex != \"\" {\n\t\tcs.Regex = q.regex\n\t}\n\n\tsuggester := make(map[string]interface{})\n\tcs.Completion = suggester\n\n\tif q.analyzer != \"\" {\n\t\tsuggester[\"analyzer\"] = q.analyzer\n\t}\n\tif q.field != \"\" {\n\t\tsuggester[\"field\"] = q.field\n\t}\n\tif q.size != nil {\n\t\tsuggester[\"size\"] = *q.size\n\t}\n\tif q.shardSize != nil {\n\t\tsuggester[\"shard_size\"] = *q.shardSize\n\t}\n\tswitch len(q.contextQueries) {\n\tcase 0:\n\tcase 1:\n\t\tsrc, err := q.contextQueries[0].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsuggester[\"contexts\"] = src\n\tdefault:\n\t\tctxq := make(map[string]interface{})\n\t\tfor _, query := range q.contextQueries {\n\t\t\tsrc, err := query.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\t// Merge the dictionary into ctxq\n\t\t\tm, ok := src.(map[string]interface{})\n\t\t\tif !ok {\n\t\t\t\treturn nil, errors.New(\"elastic: context query is not a map\")\n\t\t\t}\n\t\t\tfor k, v := range m {\n\t\t\t\tctxq[k] = v\n\t\t\t}\n\t\t}\n\t\tsuggester[\"contexts\"] = ctxq\n\t}\n\n\t// Fuzzy options\n\tif q.fuzzyOptions != nil {\n\t\tsrc, err := q.fuzzyOptions.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsuggester[\"fuzzy\"] = src\n\t}\n\n\t// Regex options\n\tif q.regexOptions != nil {\n\t\tsrc, err := q.regexOptions.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsuggester[\"regex\"] = src\n\t}\n\n\tif q.skipDuplicates != nil {\n\t\tsuggester[\"skip_duplicates\"] = *q.skipDuplicates\n\t}\n\n\t// TODO(oe) Add completion-suggester specific parameters here\n\n\tif !includeName {\n\t\treturn cs, nil\n\t}\n\n\tsource := make(map[string]interface{})\n\tsource[q.name] = cs\n\treturn source, nil\n}\n\n// -- Fuzzy options --\n\n// FuzzyCompletionSuggesterOptions represents the options for fuzzy completion suggester.\ntype FuzzyCompletionSuggesterOptions struct {\n\teditDistance          interface{}\n\ttranspositions        *bool\n\tminLength             *int\n\tprefixLength          *int\n\tunicodeAware          *bool\n\tmaxDeterminizedStates *int\n}\n\n// NewFuzzyCompletionSuggesterOptions initializes a new FuzzyCompletionSuggesterOptions instance.\nfunc NewFuzzyCompletionSuggesterOptions() *FuzzyCompletionSuggesterOptions {\n\treturn &FuzzyCompletionSuggesterOptions{}\n}\n\n// EditDistance specifies the maximum number of edits, e.g. a number like \"1\" or \"2\"\n// or a string like \"0..2\" or \">5\".\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/common-options.html#fuzziness\n// for details.\nfunc (o *FuzzyCompletionSuggesterOptions) EditDistance(editDistance interface{}) *FuzzyCompletionSuggesterOptions {\n\to.editDistance = editDistance\n\treturn o\n}\n\n// Transpositions, if set to true, are counted as one change instead of two (defaults to true).\nfunc (o *FuzzyCompletionSuggesterOptions) Transpositions(transpositions bool) *FuzzyCompletionSuggesterOptions {\n\to.transpositions = &transpositions\n\treturn o\n}\n\n// MinLength represents the minimum length of the input before fuzzy suggestions are returned (defaults to 3).\nfunc (o *FuzzyCompletionSuggesterOptions) MinLength(minLength int) *FuzzyCompletionSuggesterOptions {\n\to.minLength = &minLength\n\treturn o\n}\n\n// PrefixLength represents the minimum length of the input, which is not checked for\n// fuzzy alternatives (defaults to 1).\nfunc (o *FuzzyCompletionSuggesterOptions) PrefixLength(prefixLength int) *FuzzyCompletionSuggesterOptions {\n\to.prefixLength = &prefixLength\n\treturn o\n}\n\n// UnicodeAware, if true, all measurements (like fuzzy edit distance, transpositions, and lengths)\n// are measured in Unicode code points instead of in bytes. This is slightly slower than\n// raw bytes, so it is set to false by default.\nfunc (o *FuzzyCompletionSuggesterOptions) UnicodeAware(unicodeAware bool) *FuzzyCompletionSuggesterOptions {\n\to.unicodeAware = &unicodeAware\n\treturn o\n}\n\n// MaxDeterminizedStates is currently undocumented in Elasticsearch. It represents\n// the maximum automaton states allowed for fuzzy expansion.\nfunc (o *FuzzyCompletionSuggesterOptions) MaxDeterminizedStates(max int) *FuzzyCompletionSuggesterOptions {\n\to.maxDeterminizedStates = &max\n\treturn o\n}\n\n// Source creates the JSON data.\nfunc (o *FuzzyCompletionSuggesterOptions) Source() (interface{}, error) {\n\tout := make(map[string]interface{})\n\n\tif o.editDistance != nil {\n\t\tout[\"fuzziness\"] = o.editDistance\n\t}\n\tif o.transpositions != nil {\n\t\tout[\"transpositions\"] = *o.transpositions\n\t}\n\tif o.minLength != nil {\n\t\tout[\"min_length\"] = *o.minLength\n\t}\n\tif o.prefixLength != nil {\n\t\tout[\"prefix_length\"] = *o.prefixLength\n\t}\n\tif o.unicodeAware != nil {\n\t\tout[\"unicode_aware\"] = *o.unicodeAware\n\t}\n\tif o.maxDeterminizedStates != nil {\n\t\tout[\"max_determinized_states\"] = *o.maxDeterminizedStates\n\t}\n\n\treturn out, nil\n}\n\n// -- Regex options --\n\n// RegexCompletionSuggesterOptions represents the options for regex completion suggester.\ntype RegexCompletionSuggesterOptions struct {\n\tflags                 interface{} // string or int\n\tmaxDeterminizedStates *int\n}\n\n// NewRegexCompletionSuggesterOptions initializes a new RegexCompletionSuggesterOptions instance.\nfunc NewRegexCompletionSuggesterOptions() *RegexCompletionSuggesterOptions {\n\treturn &RegexCompletionSuggesterOptions{}\n}\n\n// Flags represents internal regex flags.\n// Possible flags are ALL (default), ANYSTRING, COMPLEMENT, EMPTY, INTERSECTION, INTERVAL, or NONE.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-completion.html#regex\n// for details.\nfunc (o *RegexCompletionSuggesterOptions) Flags(flags interface{}) *RegexCompletionSuggesterOptions {\n\to.flags = flags\n\treturn o\n}\n\n// MaxDeterminizedStates represents the maximum automaton states allowed for regex expansion.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-completion.html#regex\n// for details.\nfunc (o *RegexCompletionSuggesterOptions) MaxDeterminizedStates(max int) *RegexCompletionSuggesterOptions {\n\to.maxDeterminizedStates = &max\n\treturn o\n}\n\n// Source creates the JSON data.\nfunc (o *RegexCompletionSuggesterOptions) Source() (interface{}, error) {\n\tout := make(map[string]interface{})\n\n\tif o.flags != nil {\n\t\tout[\"flags\"] = o.flags\n\t}\n\tif o.maxDeterminizedStates != nil {\n\t\tout[\"max_determinized_states\"] = *o.maxDeterminizedStates\n\t}\n\n\treturn out, nil\n}\n"
  },
  {
    "path": "suggester_completion_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestCompletionSuggesterSource(t *testing.T) {\n\ts := NewCompletionSuggester(\"song-suggest\").\n\t\tText(\"n\").\n\t\tField(\"suggest\")\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"song-suggest\":{\"text\":\"n\",\"completion\":{\"field\":\"suggest\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCompletionSuggesterPrefixSource(t *testing.T) {\n\ts := NewCompletionSuggester(\"song-suggest\").\n\t\tPrefix(\"nir\").\n\t\tField(\"suggest\")\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"song-suggest\":{\"prefix\":\"nir\",\"completion\":{\"field\":\"suggest\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCompletionSuggesterPrefixWithFuzzySource(t *testing.T) {\n\ts := NewCompletionSuggester(\"song-suggest\").\n\t\tPrefix(\"nor\").\n\t\tField(\"suggest\").\n\t\tFuzzyOptions(NewFuzzyCompletionSuggesterOptions().EditDistance(2))\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"song-suggest\":{\"prefix\":\"nor\",\"completion\":{\"field\":\"suggest\",\"fuzzy\":{\"fuzziness\":2}}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCompletionSuggesterRegexSource(t *testing.T) {\n\ts := NewCompletionSuggester(\"song-suggest\").\n\t\tRegex(\"n[ever|i]r\").\n\t\tField(\"suggest\")\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"song-suggest\":{\"regex\":\"n[ever|i]r\",\"completion\":{\"field\":\"suggest\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestCompletionSuggesterSourceWithMultipleContexts(t *testing.T) {\n\ts := NewCompletionSuggester(\"song-suggest\").\n\t\tText(\"n\").\n\t\tField(\"suggest\").\n\t\tContextQueries(\n\t\t\tNewSuggesterCategoryQuery(\"artist\", \"Sting\"),\n\t\t\tNewSuggesterCategoryQuery(\"label\", \"BMG\"),\n\t\t)\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"song-suggest\":{\"text\":\"n\",\"completion\":{\"contexts\":{\"artist\":[{\"context\":\"Sting\"}],\"label\":[{\"context\":\"BMG\"}]},\"field\":\"suggest\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected %s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "suggester_context.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"errors\"\n\n// SuggesterContextQuery is used to define context information within\n// a suggestion request.\ntype SuggesterContextQuery interface {\n\tSource() (interface{}, error)\n}\n\n// ContextSuggester is a fast suggester for e.g. type-ahead completion that supports filtering and boosting based on contexts.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/suggester-context.html\n// for more details.\ntype ContextSuggester struct {\n\tSuggester\n\tname           string\n\tprefix         string\n\tfield          string\n\tsize           *int\n\tcontextQueries []SuggesterContextQuery\n}\n\n// Creates a new context suggester.\nfunc NewContextSuggester(name string) *ContextSuggester {\n\treturn &ContextSuggester{\n\t\tname:           name,\n\t\tcontextQueries: make([]SuggesterContextQuery, 0),\n\t}\n}\n\nfunc (q *ContextSuggester) Name() string {\n\treturn q.name\n}\n\nfunc (q *ContextSuggester) Prefix(prefix string) *ContextSuggester {\n\tq.prefix = prefix\n\treturn q\n}\n\nfunc (q *ContextSuggester) Field(field string) *ContextSuggester {\n\tq.field = field\n\treturn q\n}\n\nfunc (q *ContextSuggester) Size(size int) *ContextSuggester {\n\tq.size = &size\n\treturn q\n}\n\nfunc (q *ContextSuggester) ContextQuery(query SuggesterContextQuery) *ContextSuggester {\n\tq.contextQueries = append(q.contextQueries, query)\n\treturn q\n}\n\nfunc (q *ContextSuggester) ContextQueries(queries ...SuggesterContextQuery) *ContextSuggester {\n\tq.contextQueries = append(q.contextQueries, queries...)\n\treturn q\n}\n\n// contextSuggesterRequest is necessary because the order in which\n// the JSON elements are routed to Elasticsearch is relevant.\n// We got into trouble when using plain maps because the text element\n// needs to go before the completion element.\ntype contextSuggesterRequest struct {\n\tPrefix     string      `json:\"prefix\"`\n\tCompletion interface{} `json:\"completion\"`\n}\n\n// Creates the source for the context suggester.\nfunc (q *ContextSuggester) Source(includeName bool) (interface{}, error) {\n\tcs := &contextSuggesterRequest{}\n\n\tif q.prefix != \"\" {\n\t\tcs.Prefix = q.prefix\n\t}\n\n\tsuggester := make(map[string]interface{})\n\tcs.Completion = suggester\n\n\tif q.field != \"\" {\n\t\tsuggester[\"field\"] = q.field\n\t}\n\tif q.size != nil {\n\t\tsuggester[\"size\"] = *q.size\n\t}\n\tswitch len(q.contextQueries) {\n\tcase 0:\n\tcase 1:\n\t\tsrc, err := q.contextQueries[0].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsuggester[\"contexts\"] = src\n\tdefault:\n\t\tctxq := make(map[string]interface{})\n\t\tfor _, query := range q.contextQueries {\n\t\t\tsrc, err := query.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\t// Merge the dictionary into ctxq\n\t\t\tm, ok := src.(map[string]interface{})\n\t\t\tif !ok {\n\t\t\t\treturn nil, errors.New(\"elastic: context query is not a map\")\n\t\t\t}\n\t\t\tfor k, v := range m {\n\t\t\t\tctxq[k] = v\n\t\t\t}\n\t\t}\n\t\tsuggester[\"contexts\"] = ctxq\n\t}\n\n\tif !includeName {\n\t\treturn cs, nil\n\t}\n\n\tsource := make(map[string]interface{})\n\tsource[q.name] = cs\n\treturn source, nil\n}\n"
  },
  {
    "path": "suggester_context_category.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// -- SuggesterCategoryMapping --\n\n// SuggesterCategoryMapping provides a mapping for a category context in a suggester.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/suggester-context.html#_category_mapping.\ntype SuggesterCategoryMapping struct {\n\tname          string\n\tfieldName     string\n\tdefaultValues []string\n}\n\n// NewSuggesterCategoryMapping creates a new SuggesterCategoryMapping.\nfunc NewSuggesterCategoryMapping(name string) *SuggesterCategoryMapping {\n\treturn &SuggesterCategoryMapping{\n\t\tname:          name,\n\t\tdefaultValues: make([]string, 0),\n\t}\n}\n\nfunc (q *SuggesterCategoryMapping) DefaultValues(values ...string) *SuggesterCategoryMapping {\n\tq.defaultValues = append(q.defaultValues, values...)\n\treturn q\n}\n\nfunc (q *SuggesterCategoryMapping) FieldName(fieldName string) *SuggesterCategoryMapping {\n\tq.fieldName = fieldName\n\treturn q\n}\n\n// Source returns a map that will be used to serialize the context query as JSON.\nfunc (q *SuggesterCategoryMapping) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tx := make(map[string]interface{})\n\tsource[q.name] = x\n\n\tx[\"type\"] = \"category\"\n\n\tswitch len(q.defaultValues) {\n\tcase 0:\n\t\tx[\"default\"] = q.defaultValues\n\tcase 1:\n\t\tx[\"default\"] = q.defaultValues[0]\n\tdefault:\n\t\tx[\"default\"] = q.defaultValues\n\t}\n\n\tif q.fieldName != \"\" {\n\t\tx[\"path\"] = q.fieldName\n\t}\n\treturn source, nil\n}\n\n// -- SuggesterCategoryQuery --\n\n// SuggesterCategoryQuery provides querying a category context in a suggester.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/suggester-context.html#_category_query.\ntype SuggesterCategoryQuery struct {\n\tname   string\n\tvalues map[string]*int\n}\n\n// NewSuggesterCategoryQuery creates a new SuggesterCategoryQuery.\nfunc NewSuggesterCategoryQuery(name string, values ...string) *SuggesterCategoryQuery {\n\tq := &SuggesterCategoryQuery{\n\t\tname:   name,\n\t\tvalues: make(map[string]*int),\n\t}\n\n\tif len(values) > 0 {\n\t\tq.Values(values...)\n\t}\n\treturn q\n}\n\nfunc (q *SuggesterCategoryQuery) Value(val string) *SuggesterCategoryQuery {\n\tq.values[val] = nil\n\treturn q\n}\n\nfunc (q *SuggesterCategoryQuery) ValueWithBoost(val string, boost int) *SuggesterCategoryQuery {\n\tq.values[val] = &boost\n\treturn q\n}\n\nfunc (q *SuggesterCategoryQuery) Values(values ...string) *SuggesterCategoryQuery {\n\tfor _, val := range values {\n\t\tq.values[val] = nil\n\t}\n\treturn q\n}\n\n// Source returns a map that will be used to serialize the context query as JSON.\nfunc (q *SuggesterCategoryQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tswitch len(q.values) {\n\tcase 0:\n\t\tsource[q.name] = make([]string, 0)\n\tdefault:\n\t\tcontexts := make([]interface{}, 0)\n\t\tfor val, boost := range q.values {\n\t\t\tcontext := make(map[string]interface{})\n\t\t\tcontext[\"context\"] = val\n\t\t\tif boost != nil {\n\t\t\t\tcontext[\"boost\"] = *boost\n\t\t\t}\n\t\t\tcontexts = append(contexts, context)\n\t\t}\n\t\tsource[q.name] = contexts\n\t}\n\n\treturn source, nil\n}\n\ntype SuggesterCategoryIndex struct {\n\tname   string\n\tvalues []string\n}\n\n// NewSuggesterCategoryIndex creates a new SuggesterCategoryIndex.\nfunc NewSuggesterCategoryIndex(name string, values ...string) *SuggesterCategoryIndex {\n\tq := &SuggesterCategoryIndex{\n\t\tname:   name,\n\t\tvalues: values,\n\t}\n\treturn q\n}\n\nfunc (q *SuggesterCategoryIndex) Values(values ...string) *SuggesterCategoryIndex {\n\tq.values = append(q.values, values...)\n\treturn q\n}\n\n// Source returns a map that will be used to serialize the context query as JSON.\nfunc (q *SuggesterCategoryIndex) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tswitch len(q.values) {\n\tcase 0:\n\t\tsource[q.name] = make([]string, 0)\n\tcase 1:\n\t\tsource[q.name] = q.values[0]\n\tdefault:\n\t\tsource[q.name] = q.values\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "suggester_context_category_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSuggesterCategoryMapping(t *testing.T) {\n\tq := NewSuggesterCategoryMapping(\"color\").DefaultValues(\"red\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"color\":{\"default\":\"red\",\"type\":\"category\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSuggesterCategoryMappingWithTwoDefaultValues(t *testing.T) {\n\tq := NewSuggesterCategoryMapping(\"color\").DefaultValues(\"red\", \"orange\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"color\":{\"default\":[\"red\",\"orange\"],\"type\":\"category\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSuggesterCategoryMappingWithFieldName(t *testing.T) {\n\tq := NewSuggesterCategoryMapping(\"color\").\n\t\tDefaultValues(\"red\", \"orange\").\n\t\tFieldName(\"color_field\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"color\":{\"default\":[\"red\",\"orange\"],\"path\":\"color_field\",\"type\":\"category\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSuggesterCategoryQuery(t *testing.T) {\n\tq := NewSuggesterCategoryQuery(\"color\", \"red\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"color\":[{\"context\":\"red\"}]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSuggesterCategoryQueryWithTwoValues(t *testing.T) {\n\tq := NewSuggesterCategoryQuery(\"color\", \"red\", \"yellow\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpectedOutcomes := []string{\n\t\t`{\"color\":[{\"context\":\"red\"},{\"context\":\"yellow\"}]}`,\n\t\t`{\"color\":[{\"context\":\"yellow\"},{\"context\":\"red\"}]}`,\n\t}\n\tvar match bool\n\tfor _, expected := range expectedOutcomes {\n\t\tif got == expected {\n\t\t\tmatch = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !match {\n\t\tt.Errorf(\"expected any of %v\\n,got:\\n%s\", expectedOutcomes, got)\n\t}\n}\n\nfunc TestSuggesterCategoryQueryWithBoost(t *testing.T) {\n\tq := NewSuggesterCategoryQuery(\"color\", \"red\")\n\tq.ValueWithBoost(\"yellow\", 4)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpectedOutcomes := []string{\n\t\t`{\"color\":[{\"context\":\"red\"},{\"boost\":4,\"context\":\"yellow\"}]}`,\n\t\t`{\"color\":[{\"boost\":4,\"context\":\"yellow\"},{\"context\":\"red\"}]}`,\n\t}\n\tvar match bool\n\tfor _, expected := range expectedOutcomes {\n\t\tif got == expected {\n\t\t\tmatch = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !match {\n\t\tt.Errorf(\"expected any of %v\\n,got:\\n%v\", expectedOutcomes, got)\n\t}\n}\n\nfunc TestSuggesterCategoryQueryWithoutBoost(t *testing.T) {\n\tq := NewSuggesterCategoryQuery(\"color\", \"red\")\n\tq.Value(\"yellow\")\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpectedOutcomes := []string{\n\t\t`{\"color\":[{\"context\":\"red\"},{\"context\":\"yellow\"}]}`,\n\t\t`{\"color\":[{\"context\":\"yellow\"},{\"context\":\"red\"}]}`,\n\t}\n\tvar match bool\n\tfor _, expected := range expectedOutcomes {\n\t\tif got == expected {\n\t\t\tmatch = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !match {\n\t\tt.Errorf(\"expected any of %v\\n,got:\\n%s\", expectedOutcomes, got)\n\t}\n}\n\nfunc TestSuggesterCategoryIndex(t *testing.T) {\n\tin := NewSuggesterCategoryIndex(\"color\", \"red\")\n\tsrc, err := in.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"color\":\"red\"}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSuggesterCategoryIndexWithTwoValues(t *testing.T) {\n\tin := NewSuggesterCategoryIndex(\"color\", \"red\", \"yellow\")\n\tsrc, err := in.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"color\":[\"red\",\"yellow\"]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "suggester_context_geo.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// -- SuggesterGeoMapping --\n\n// SuggesterGeoMapping provides a mapping for a geolocation context in a suggester.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/suggester-context.html#_geo_location_mapping.\ntype SuggesterGeoMapping struct {\n\tname             string\n\tdefaultLocations []*GeoPoint\n\tprecision        []string\n\tneighbors        *bool\n\tfieldName        string\n}\n\n// NewSuggesterGeoMapping creates a new SuggesterGeoMapping.\nfunc NewSuggesterGeoMapping(name string) *SuggesterGeoMapping {\n\treturn &SuggesterGeoMapping{\n\t\tname: name,\n\t}\n}\n\nfunc (q *SuggesterGeoMapping) DefaultLocations(locations ...*GeoPoint) *SuggesterGeoMapping {\n\tq.defaultLocations = append(q.defaultLocations, locations...)\n\treturn q\n}\n\nfunc (q *SuggesterGeoMapping) Precision(precision ...string) *SuggesterGeoMapping {\n\tq.precision = append(q.precision, precision...)\n\treturn q\n}\n\nfunc (q *SuggesterGeoMapping) Neighbors(neighbors bool) *SuggesterGeoMapping {\n\tq.neighbors = &neighbors\n\treturn q\n}\n\nfunc (q *SuggesterGeoMapping) FieldName(fieldName string) *SuggesterGeoMapping {\n\tq.fieldName = fieldName\n\treturn q\n}\n\n// Source returns a map that will be used to serialize the context query as JSON.\nfunc (q *SuggesterGeoMapping) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tx := make(map[string]interface{})\n\tsource[q.name] = x\n\n\tx[\"type\"] = \"geo\"\n\n\tif len(q.precision) > 0 {\n\t\tx[\"precision\"] = q.precision\n\t}\n\tif q.neighbors != nil {\n\t\tx[\"neighbors\"] = *q.neighbors\n\t}\n\n\tswitch len(q.defaultLocations) {\n\tcase 0:\n\tcase 1:\n\t\tx[\"default\"] = q.defaultLocations[0].Source()\n\tdefault:\n\t\tvar arr []interface{}\n\t\tfor _, p := range q.defaultLocations {\n\t\t\tarr = append(arr, p.Source())\n\t\t}\n\t\tx[\"default\"] = arr\n\t}\n\n\tif q.fieldName != \"\" {\n\t\tx[\"path\"] = q.fieldName\n\t}\n\treturn source, nil\n}\n\n// -- SuggesterGeoQuery --\n\n// SuggesterGeoQuery provides querying a geolocation context in a suggester.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/suggester-context.html#_geo_location_query\ntype SuggesterGeoQuery struct {\n\tname       string\n\tlocation   *GeoPoint\n\tprecision  string\n\tneighbours []string\n\tboost      *int\n}\n\n// NewSuggesterGeoQuery creates a new SuggesterGeoQuery.\nfunc NewSuggesterGeoQuery(name string, location *GeoPoint) *SuggesterGeoQuery {\n\treturn &SuggesterGeoQuery{\n\t\tname:       name,\n\t\tlocation:   location,\n\t\tneighbours: make([]string, 0),\n\t}\n}\n\nfunc (q *SuggesterGeoQuery) Precision(precision string) *SuggesterGeoQuery {\n\tq.precision = precision\n\treturn q\n}\n\nfunc (q *SuggesterGeoQuery) Neighbours(neighbours ...string) *SuggesterGeoQuery {\n\tq.neighbours = append(q.neighbours, neighbours...)\n\treturn q\n}\n\nfunc (q *SuggesterGeoQuery) Boost(boost int) *SuggesterGeoQuery {\n\tq.boost = &boost\n\treturn q\n}\n\n// Source returns a map that will be used to serialize the context query as JSON.\nfunc (q *SuggesterGeoQuery) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tx := make(map[string]interface{})\n\tsource[q.name] = x\n\n\tif q.location != nil {\n\t\tx[\"context\"] = q.location.Source()\n\t}\n\tif q.precision != \"\" {\n\t\tx[\"precision\"] = q.precision\n\t}\n\tif q.boost != nil {\n\t\tx[\"boost\"] = q.boost\n\t}\n\tswitch len(q.neighbours) {\n\tcase 0:\n\tcase 1:\n\t\tx[\"neighbours\"] = q.neighbours[0]\n\tdefault:\n\t\tx[\"neighbours\"] = q.neighbours\n\t}\n\n\treturn source, nil\n}\n\ntype SuggesterGeoIndex struct {\n\tname      string\n\tlocations []*GeoPoint\n}\n\n// NewSuggesterGeoQuery creates a new SuggesterGeoQuery.\nfunc NewSuggesterGeoIndex(name string) *SuggesterGeoIndex {\n\treturn &SuggesterGeoIndex{\n\t\tname: name,\n\t}\n}\n\nfunc (q *SuggesterGeoIndex) Locations(locations ...*GeoPoint) *SuggesterGeoIndex {\n\tq.locations = append(q.locations, locations...)\n\treturn q\n}\n\n// Source returns a map that will be used to serialize the context query as JSON.\nfunc (q *SuggesterGeoIndex) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tswitch len(q.locations) {\n\tcase 0:\n\t\tsource[q.name] = make([]string, 0)\n\tcase 1:\n\t\tsource[q.name] = q.locations[0].Source()\n\tdefault:\n\t\tvar arr []interface{}\n\t\tfor _, p := range q.locations {\n\t\t\tarr = append(arr, p.Source())\n\t\t}\n\t\tsource[q.name] = arr\n\t}\n\n\treturn source, nil\n}\n"
  },
  {
    "path": "suggester_context_geo_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestSuggesterGeoMapping(t *testing.T) {\n\tq := NewSuggesterGeoMapping(\"location\").\n\t\tPrecision(\"1km\", \"5m\").\n\t\tNeighbors(true).\n\t\tFieldName(\"pin\").\n\t\tDefaultLocations(GeoPointFromLatLon(0.0, 0.0))\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"location\":{\"default\":{\"lat\":0,\"lon\":0},\"neighbors\":true,\"path\":\"pin\",\"precision\":[\"1km\",\"5m\"],\"type\":\"geo\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSuggesterGeoQuery(t *testing.T) {\n\tq := NewSuggesterGeoQuery(\"location\", GeoPointFromLatLon(11.5, 62.71)).Precision(\"1km\").\n\t\tNeighbours(\"2km\", \"3km\").Boost(2)\n\tsrc, err := q.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpectedOutcomes := []string{\n\t\t`{\"location\":{\"context\":{\"lat\":11.5,\"lon\":62.71},\"precision\":\"1km\",\"boost\":2,\"neighbours\":[\"2km\",\"3km\"]}}`,\n\t\t`{\"location\":{\"boost\":2,\"context\":{\"lat\":11.5,\"lon\":62.71},\"neighbours\":[\"2km\",\"3km\"],\"precision\":\"1km\"}}`,\n\t}\n\tvar match bool\n\tfor _, expected := range expectedOutcomes {\n\t\tif got == expected {\n\t\t\tmatch = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !match {\n\t\tt.Errorf(\"expected any of %v\\n,got:\\n%s\", expectedOutcomes, got)\n\t}\n}\n\nfunc TestSuggesterGeoIndex(t *testing.T) {\n\tin := NewSuggesterGeoIndex(\"location\").Locations(GeoPointFromLatLon(11.5, 62.71))\n\tsrc, err := in.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"location\":{\"lat\":11.5,\"lon\":62.71}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestSuggesterGeoIndexWithTwoValues(t *testing.T) {\n\tin := NewSuggesterGeoIndex(\"location\").Locations(GeoPointFromLatLon(11.5, 62.71), GeoPointFromLatLon(31.5, 22.71))\n\tsrc, err := in.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"location\":[{\"lat\":11.5,\"lon\":62.71},{\"lat\":31.5,\"lon\":22.71}]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "suggester_context_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestContextSuggesterSource(t *testing.T) {\n\ts := NewContextSuggester(\"place_suggestion\").\n\t\tPrefix(\"tim\").\n\t\tField(\"suggest\")\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"place_suggestion\":{\"prefix\":\"tim\",\"completion\":{\"field\":\"suggest\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestContextSuggesterSourceWithMultipleContexts(t *testing.T) {\n\ts := NewContextSuggester(\"place_suggestion\").\n\t\tPrefix(\"tim\").\n\t\tField(\"suggest\").\n\t\tContextQueries(\n\t\t\tNewSuggesterCategoryQuery(\"place_type\", \"cafe\", \"restaurants\"),\n\t\t)\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\t// Due to the randomization of dictionary key, we could actually have two different valid expected outcomes\n\texpected := `{\"place_suggestion\":{\"prefix\":\"tim\",\"completion\":{\"contexts\":{\"place_type\":[{\"context\":\"cafe\"},{\"context\":\"restaurants\"}]},\"field\":\"suggest\"}}}`\n\tif got != expected {\n\t\texpected := `{\"place_suggestion\":{\"prefix\":\"tim\",\"completion\":{\"contexts\":{\"place_type\":[{\"context\":\"restaurants\"},{\"context\":\"cafe\"}]},\"field\":\"suggest\"}}}`\n\t\tif got != expected {\n\t\t\tt.Errorf(\"expected %s\\n,got:\\n%s\", expected, got)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "suggester_phrase.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// PhraseSuggester provides an API to access word alternatives\n// on a per token basis within a certain string distance.\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-phrase.html.\ntype PhraseSuggester struct {\n\tSuggester\n\tname           string\n\ttext           string\n\tfield          string\n\tanalyzer       string\n\tsize           *int\n\tshardSize      *int\n\tcontextQueries []SuggesterContextQuery\n\n\t// fields specific to a phrase suggester\n\tmaxErrors               *float64\n\tseparator               *string\n\trealWordErrorLikelihood *float64\n\tconfidence              *float64\n\tgenerators              map[string][]CandidateGenerator\n\tgramSize                *int\n\tsmoothingModel          SmoothingModel\n\tforceUnigrams           *bool\n\ttokenLimit              *int\n\tpreTag, postTag         *string\n\tcollateQuery            *Script\n\tcollatePreference       *string\n\tcollateParams           map[string]interface{}\n\tcollatePrune            *bool\n}\n\n// NewPhraseSuggester creates a new PhraseSuggester.\nfunc NewPhraseSuggester(name string) *PhraseSuggester {\n\treturn &PhraseSuggester{\n\t\tname:          name,\n\t\tcollateParams: make(map[string]interface{}),\n\t}\n}\n\nfunc (q *PhraseSuggester) Name() string {\n\treturn q.name\n}\n\nfunc (q *PhraseSuggester) Text(text string) *PhraseSuggester {\n\tq.text = text\n\treturn q\n}\n\nfunc (q *PhraseSuggester) Field(field string) *PhraseSuggester {\n\tq.field = field\n\treturn q\n}\n\nfunc (q *PhraseSuggester) Analyzer(analyzer string) *PhraseSuggester {\n\tq.analyzer = analyzer\n\treturn q\n}\n\nfunc (q *PhraseSuggester) Size(size int) *PhraseSuggester {\n\tq.size = &size\n\treturn q\n}\n\nfunc (q *PhraseSuggester) ShardSize(shardSize int) *PhraseSuggester {\n\tq.shardSize = &shardSize\n\treturn q\n}\n\nfunc (q *PhraseSuggester) ContextQuery(query SuggesterContextQuery) *PhraseSuggester {\n\tq.contextQueries = append(q.contextQueries, query)\n\treturn q\n}\n\nfunc (q *PhraseSuggester) ContextQueries(queries ...SuggesterContextQuery) *PhraseSuggester {\n\tq.contextQueries = append(q.contextQueries, queries...)\n\treturn q\n}\n\nfunc (q *PhraseSuggester) GramSize(gramSize int) *PhraseSuggester {\n\tif gramSize >= 1 {\n\t\tq.gramSize = &gramSize\n\t}\n\treturn q\n}\n\nfunc (q *PhraseSuggester) MaxErrors(maxErrors float64) *PhraseSuggester {\n\tq.maxErrors = &maxErrors\n\treturn q\n}\n\nfunc (q *PhraseSuggester) Separator(separator string) *PhraseSuggester {\n\tq.separator = &separator\n\treturn q\n}\n\nfunc (q *PhraseSuggester) RealWordErrorLikelihood(realWordErrorLikelihood float64) *PhraseSuggester {\n\tq.realWordErrorLikelihood = &realWordErrorLikelihood\n\treturn q\n}\n\nfunc (q *PhraseSuggester) Confidence(confidence float64) *PhraseSuggester {\n\tq.confidence = &confidence\n\treturn q\n}\n\nfunc (q *PhraseSuggester) CandidateGenerator(generator CandidateGenerator) *PhraseSuggester {\n\tif q.generators == nil {\n\t\tq.generators = make(map[string][]CandidateGenerator)\n\t}\n\ttyp := generator.Type()\n\tif _, found := q.generators[typ]; !found {\n\t\tq.generators[typ] = make([]CandidateGenerator, 0)\n\t}\n\tq.generators[typ] = append(q.generators[typ], generator)\n\treturn q\n}\n\nfunc (q *PhraseSuggester) CandidateGenerators(generators ...CandidateGenerator) *PhraseSuggester {\n\tfor _, g := range generators {\n\t\tq = q.CandidateGenerator(g)\n\t}\n\treturn q\n}\n\nfunc (q *PhraseSuggester) ClearCandidateGenerator() *PhraseSuggester {\n\tq.generators = nil\n\treturn q\n}\n\nfunc (q *PhraseSuggester) ForceUnigrams(forceUnigrams bool) *PhraseSuggester {\n\tq.forceUnigrams = &forceUnigrams\n\treturn q\n}\n\nfunc (q *PhraseSuggester) SmoothingModel(smoothingModel SmoothingModel) *PhraseSuggester {\n\tq.smoothingModel = smoothingModel\n\treturn q\n}\n\nfunc (q *PhraseSuggester) TokenLimit(tokenLimit int) *PhraseSuggester {\n\tq.tokenLimit = &tokenLimit\n\treturn q\n}\n\nfunc (q *PhraseSuggester) Highlight(preTag, postTag string) *PhraseSuggester {\n\tq.preTag = &preTag\n\tq.postTag = &postTag\n\treturn q\n}\n\nfunc (q *PhraseSuggester) CollateQuery(collateQuery *Script) *PhraseSuggester {\n\tq.collateQuery = collateQuery\n\treturn q\n}\n\nfunc (q *PhraseSuggester) CollatePreference(collatePreference string) *PhraseSuggester {\n\tq.collatePreference = &collatePreference\n\treturn q\n}\n\nfunc (q *PhraseSuggester) CollateParams(collateParams map[string]interface{}) *PhraseSuggester {\n\tq.collateParams = collateParams\n\treturn q\n}\n\nfunc (q *PhraseSuggester) CollatePrune(collatePrune bool) *PhraseSuggester {\n\tq.collatePrune = &collatePrune\n\treturn q\n}\n\n// phraseSuggesterRequest is necessary because the order in which\n// the JSON elements are routed to Elasticsearch is relevant.\n// We got into trouble when using plain maps because the text element\n// needs to go before the simple_phrase element.\ntype phraseSuggesterRequest struct {\n\tText   string      `json:\"text\"`\n\tPhrase interface{} `json:\"phrase\"`\n}\n\n// Source generates the source for the phrase suggester.\nfunc (q *PhraseSuggester) Source(includeName bool) (interface{}, error) {\n\tps := &phraseSuggesterRequest{}\n\n\tif q.text != \"\" {\n\t\tps.Text = q.text\n\t}\n\n\tsuggester := make(map[string]interface{})\n\tps.Phrase = suggester\n\n\tif q.analyzer != \"\" {\n\t\tsuggester[\"analyzer\"] = q.analyzer\n\t}\n\tif q.field != \"\" {\n\t\tsuggester[\"field\"] = q.field\n\t}\n\tif q.size != nil {\n\t\tsuggester[\"size\"] = *q.size\n\t}\n\tif q.shardSize != nil {\n\t\tsuggester[\"shard_size\"] = *q.shardSize\n\t}\n\tswitch len(q.contextQueries) {\n\tcase 0:\n\tcase 1:\n\t\tsrc, err := q.contextQueries[0].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsuggester[\"contexts\"] = src\n\tdefault:\n\t\tvar ctxq []interface{}\n\t\tfor _, query := range q.contextQueries {\n\t\t\tsrc, err := query.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tctxq = append(ctxq, src)\n\t\t}\n\t\tsuggester[\"contexts\"] = ctxq\n\t}\n\n\t// Phase-specified parameters\n\tif q.realWordErrorLikelihood != nil {\n\t\tsuggester[\"real_word_error_likelihood\"] = *q.realWordErrorLikelihood\n\t}\n\tif q.confidence != nil {\n\t\tsuggester[\"confidence\"] = *q.confidence\n\t}\n\tif q.separator != nil {\n\t\tsuggester[\"separator\"] = *q.separator\n\t}\n\tif q.maxErrors != nil {\n\t\tsuggester[\"max_errors\"] = *q.maxErrors\n\t}\n\tif q.gramSize != nil {\n\t\tsuggester[\"gram_size\"] = *q.gramSize\n\t}\n\tif q.forceUnigrams != nil {\n\t\tsuggester[\"force_unigrams\"] = *q.forceUnigrams\n\t}\n\tif q.tokenLimit != nil {\n\t\tsuggester[\"token_limit\"] = *q.tokenLimit\n\t}\n\tif q.generators != nil && len(q.generators) > 0 {\n\t\tfor typ, generators := range q.generators {\n\t\t\tvar arr []interface{}\n\t\t\tfor _, g := range generators {\n\t\t\t\tsrc, err := g.Source()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t\tarr = append(arr, src)\n\t\t\t}\n\t\t\tsuggester[typ] = arr\n\t\t}\n\t}\n\tif q.smoothingModel != nil {\n\t\tsrc, err := q.smoothingModel.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tx := make(map[string]interface{})\n\t\tx[q.smoothingModel.Type()] = src\n\t\tsuggester[\"smoothing\"] = x\n\t}\n\tif q.preTag != nil {\n\t\thl := make(map[string]string)\n\t\thl[\"pre_tag\"] = *q.preTag\n\t\tif q.postTag != nil {\n\t\t\thl[\"post_tag\"] = *q.postTag\n\t\t}\n\t\tsuggester[\"highlight\"] = hl\n\t}\n\tif q.collateQuery != nil {\n\t\tcollate := make(map[string]interface{})\n\t\tsuggester[\"collate\"] = collate\n\t\tif q.collateQuery != nil {\n\t\t\tsrc, err := q.collateQuery.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tcollate[\"query\"] = src\n\t\t}\n\t\tif q.collatePreference != nil {\n\t\t\tcollate[\"preference\"] = *q.collatePreference\n\t\t}\n\t\tif len(q.collateParams) > 0 {\n\t\t\tcollate[\"params\"] = q.collateParams\n\t\t}\n\t\tif q.collatePrune != nil {\n\t\t\tcollate[\"prune\"] = *q.collatePrune\n\t\t}\n\t}\n\n\tif !includeName {\n\t\treturn ps, nil\n\t}\n\n\tsource := make(map[string]interface{})\n\tsource[q.name] = ps\n\treturn source, nil\n}\n\n// -- Smoothing models --\n\ntype SmoothingModel interface {\n\tType() string\n\tSource() (interface{}, error)\n}\n\n// StupidBackoffSmoothingModel implements a stupid backoff smoothing model.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-phrase.html#_smoothing_models\n// for details about smoothing models.\ntype StupidBackoffSmoothingModel struct {\n\tdiscount float64\n}\n\nfunc NewStupidBackoffSmoothingModel(discount float64) *StupidBackoffSmoothingModel {\n\treturn &StupidBackoffSmoothingModel{\n\t\tdiscount: discount,\n\t}\n}\n\nfunc (sm *StupidBackoffSmoothingModel) Type() string {\n\treturn \"stupid_backoff\"\n}\n\nfunc (sm *StupidBackoffSmoothingModel) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tsource[\"discount\"] = sm.discount\n\treturn source, nil\n}\n\n// --\n\n// LaplaceSmoothingModel implements a laplace smoothing model.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-phrase.html#_smoothing_models\n// for details about smoothing models.\ntype LaplaceSmoothingModel struct {\n\talpha float64\n}\n\nfunc NewLaplaceSmoothingModel(alpha float64) *LaplaceSmoothingModel {\n\treturn &LaplaceSmoothingModel{\n\t\talpha: alpha,\n\t}\n}\n\nfunc (sm *LaplaceSmoothingModel) Type() string {\n\treturn \"laplace\"\n}\n\nfunc (sm *LaplaceSmoothingModel) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tsource[\"alpha\"] = sm.alpha\n\treturn source, nil\n}\n\n// --\n\n// LinearInterpolationSmoothingModel implements a linear interpolation\n// smoothing model.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-phrase.html#_smoothing_models\n// for details about smoothing models.\ntype LinearInterpolationSmoothingModel struct {\n\ttrigramLamda  float64\n\tbigramLambda  float64\n\tunigramLambda float64\n}\n\nfunc NewLinearInterpolationSmoothingModel(trigramLamda, bigramLambda, unigramLambda float64) *LinearInterpolationSmoothingModel {\n\treturn &LinearInterpolationSmoothingModel{\n\t\ttrigramLamda:  trigramLamda,\n\t\tbigramLambda:  bigramLambda,\n\t\tunigramLambda: unigramLambda,\n\t}\n}\n\nfunc (sm *LinearInterpolationSmoothingModel) Type() string {\n\treturn \"linear_interpolation\"\n}\n\nfunc (sm *LinearInterpolationSmoothingModel) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tsource[\"trigram_lambda\"] = sm.trigramLamda\n\tsource[\"bigram_lambda\"] = sm.bigramLambda\n\tsource[\"unigram_lambda\"] = sm.unigramLambda\n\treturn source, nil\n}\n\n// -- CandidateGenerator --\n\ntype CandidateGenerator interface {\n\tType() string\n\tSource() (interface{}, error)\n}\n\n// DirectCandidateGenerator implements a direct candidate generator.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-phrase.html#_smoothing_models\n// for details about smoothing models.\ntype DirectCandidateGenerator struct {\n\tfield          string\n\tpreFilter      *string\n\tpostFilter     *string\n\tsuggestMode    *string\n\taccuracy       *float64\n\tsize           *int\n\tsort           *string\n\tstringDistance *string\n\tmaxEdits       *int\n\tmaxInspections *int\n\tmaxTermFreq    *float64\n\tprefixLength   *int\n\tminWordLength  *int\n\tminDocFreq     *float64\n}\n\nfunc NewDirectCandidateGenerator(field string) *DirectCandidateGenerator {\n\treturn &DirectCandidateGenerator{\n\t\tfield: field,\n\t}\n}\n\nfunc (g *DirectCandidateGenerator) Type() string {\n\treturn \"direct_generator\"\n}\n\nfunc (g *DirectCandidateGenerator) Field(field string) *DirectCandidateGenerator {\n\tg.field = field\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) PreFilter(preFilter string) *DirectCandidateGenerator {\n\tg.preFilter = &preFilter\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) PostFilter(postFilter string) *DirectCandidateGenerator {\n\tg.postFilter = &postFilter\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) SuggestMode(suggestMode string) *DirectCandidateGenerator {\n\tg.suggestMode = &suggestMode\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) Accuracy(accuracy float64) *DirectCandidateGenerator {\n\tg.accuracy = &accuracy\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) Size(size int) *DirectCandidateGenerator {\n\tg.size = &size\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) Sort(sort string) *DirectCandidateGenerator {\n\tg.sort = &sort\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) StringDistance(stringDistance string) *DirectCandidateGenerator {\n\tg.stringDistance = &stringDistance\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) MaxEdits(maxEdits int) *DirectCandidateGenerator {\n\tg.maxEdits = &maxEdits\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) MaxInspections(maxInspections int) *DirectCandidateGenerator {\n\tg.maxInspections = &maxInspections\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) MaxTermFreq(maxTermFreq float64) *DirectCandidateGenerator {\n\tg.maxTermFreq = &maxTermFreq\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) PrefixLength(prefixLength int) *DirectCandidateGenerator {\n\tg.prefixLength = &prefixLength\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) MinWordLength(minWordLength int) *DirectCandidateGenerator {\n\tg.minWordLength = &minWordLength\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) MinDocFreq(minDocFreq float64) *DirectCandidateGenerator {\n\tg.minDocFreq = &minDocFreq\n\treturn g\n}\n\nfunc (g *DirectCandidateGenerator) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif g.field != \"\" {\n\t\tsource[\"field\"] = g.field\n\t}\n\tif g.suggestMode != nil {\n\t\tsource[\"suggest_mode\"] = *g.suggestMode\n\t}\n\tif g.accuracy != nil {\n\t\tsource[\"accuracy\"] = *g.accuracy\n\t}\n\tif g.size != nil {\n\t\tsource[\"size\"] = *g.size\n\t}\n\tif g.sort != nil {\n\t\tsource[\"sort\"] = *g.sort\n\t}\n\tif g.stringDistance != nil {\n\t\tsource[\"string_distance\"] = *g.stringDistance\n\t}\n\tif g.maxEdits != nil {\n\t\tsource[\"max_edits\"] = *g.maxEdits\n\t}\n\tif g.maxInspections != nil {\n\t\tsource[\"max_inspections\"] = *g.maxInspections\n\t}\n\tif g.maxTermFreq != nil {\n\t\tsource[\"max_term_freq\"] = *g.maxTermFreq\n\t}\n\tif g.prefixLength != nil {\n\t\tsource[\"prefix_length\"] = *g.prefixLength\n\t}\n\tif g.minWordLength != nil {\n\t\tsource[\"min_word_length\"] = *g.minWordLength\n\t}\n\tif g.minDocFreq != nil {\n\t\tsource[\"min_doc_freq\"] = *g.minDocFreq\n\t}\n\tif g.preFilter != nil {\n\t\tsource[\"pre_filter\"] = *g.preFilter\n\t}\n\tif g.postFilter != nil {\n\t\tsource[\"post_filter\"] = *g.postFilter\n\t}\n\treturn source, nil\n}\n"
  },
  {
    "path": "suggester_phrase_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestPhraseSuggesterSource(t *testing.T) {\n\ts := NewPhraseSuggester(\"name\").\n\t\tText(\"Xor the Got-Jewel\").\n\t\tAnalyzer(\"body\").\n\t\tField(\"bigram\").\n\t\tSize(1).\n\t\tRealWordErrorLikelihood(0.95).\n\t\tMaxErrors(0.5).\n\t\tGramSize(2).\n\t\tHighlight(\"<em>\", \"</em>\")\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"name\":{\"text\":\"Xor the Got-Jewel\",\"phrase\":{\"analyzer\":\"body\",\"field\":\"bigram\",\"gram_size\":2,\"highlight\":{\"post_tag\":\"\\u003c/em\\u003e\",\"pre_tag\":\"\\u003cem\\u003e\"},\"max_errors\":0.5,\"real_word_error_likelihood\":0.95,\"size\":1}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPhraseSuggesterSourceWithContextQuery(t *testing.T) {\n\tgeomapQ := NewSuggesterGeoMapping(\"location\").\n\t\tPrecision(\"1km\", \"5m\").\n\t\tNeighbors(true).\n\t\tFieldName(\"pin\").\n\t\tDefaultLocations(GeoPointFromLatLon(0.0, 0.0))\n\n\ts := NewPhraseSuggester(\"name\").\n\t\tText(\"Xor the Got-Jewel\").\n\t\tAnalyzer(\"body\").\n\t\tField(\"bigram\").\n\t\tSize(1).\n\t\tRealWordErrorLikelihood(0.95).\n\t\tMaxErrors(0.5).\n\t\tGramSize(2).\n\t\tHighlight(\"<em>\", \"</em>\").\n\t\tContextQuery(geomapQ)\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"name\":{\"text\":\"Xor the Got-Jewel\",\"phrase\":{\"analyzer\":\"body\",\"contexts\":{\"location\":{\"default\":{\"lat\":0,\"lon\":0},\"neighbors\":true,\"path\":\"pin\",\"precision\":[\"1km\",\"5m\"],\"type\":\"geo\"}},\"field\":\"bigram\",\"gram_size\":2,\"highlight\":{\"post_tag\":\"\\u003c/em\\u003e\",\"pre_tag\":\"\\u003cem\\u003e\"},\"max_errors\":0.5,\"real_word_error_likelihood\":0.95,\"size\":1}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPhraseSuggesterComplexSource(t *testing.T) {\n\tg1 := NewDirectCandidateGenerator(\"body\").\n\t\tSuggestMode(\"always\").\n\t\tMinWordLength(1)\n\n\tg2 := NewDirectCandidateGenerator(\"reverse\").\n\t\tSuggestMode(\"always\").\n\t\tMinWordLength(1).\n\t\tPreFilter(\"reverse\").\n\t\tPostFilter(\"reverse\")\n\n\ts := NewPhraseSuggester(\"simple_phrase\").\n\t\tText(\"Xor the Got-Jewel\").\n\t\tAnalyzer(\"body\").\n\t\tField(\"bigram\").\n\t\tSize(4).\n\t\tRealWordErrorLikelihood(0.95).\n\t\tConfidence(2.0).\n\t\tGramSize(2).\n\t\tCandidateGenerators(g1, g2).\n\t\tCollateQuery(\n\t\t\tNewScriptInline(`{\"match\":{\"{{field_name}}\" : \"{{suggestion}}\"}}`),\n\t\t).\n\t\tCollateParams(map[string]interface{}{\"field_name\": \"title\"}).\n\t\tCollatePreference(\"_primary\").\n\t\tCollatePrune(true)\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"simple_phrase\":{\"text\":\"Xor the Got-Jewel\",\"phrase\":{\"analyzer\":\"body\",\"collate\":{\"params\":{\"field_name\":\"title\"},\"preference\":\"_primary\",\"prune\":true,\"query\":{\"source\":{\"match\":{\"{{field_name}}\":\"{{suggestion}}\"}}}},\"confidence\":2,\"direct_generator\":[{\"field\":\"body\",\"min_word_length\":1,\"suggest_mode\":\"always\"},{\"field\":\"reverse\",\"min_word_length\":1,\"post_filter\":\"reverse\",\"pre_filter\":\"reverse\",\"suggest_mode\":\"always\"}],\"field\":\"bigram\",\"gram_size\":2,\"real_word_error_likelihood\":0.95,\"size\":4}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestPhraseStupidBackoffSmoothingModel(t *testing.T) {\n\ts := NewStupidBackoffSmoothingModel(0.42)\n\tsrc, err := s.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\t// The source does NOT include the smoothing model type!\n\texpected := `{\"discount\":0.42}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n\tif s.Type() != \"stupid_backoff\" {\n\t\tt.Errorf(\"expected %q, got: %q\", \"stupid_backoff\", s.Type())\n\t}\n}\n\nfunc TestPhraseLaplaceSmoothingModel(t *testing.T) {\n\ts := NewLaplaceSmoothingModel(0.63)\n\tsrc, err := s.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\t// The source does NOT include the smoothing model type!\n\texpected := `{\"alpha\":0.63}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n\tif s.Type() != \"laplace\" {\n\t\tt.Errorf(\"expected %q, got: %q\", \"laplace\", s.Type())\n\t}\n}\n\nfunc TestLinearInterpolationSmoothingModel(t *testing.T) {\n\ts := NewLinearInterpolationSmoothingModel(0.3, 0.2, 0.05)\n\tsrc, err := s.Source()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\t// The source does NOT include the smoothing model type!\n\texpected := `{\"bigram_lambda\":0.2,\"trigram_lambda\":0.3,\"unigram_lambda\":0.05}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n\tif s.Type() != \"linear_interpolation\" {\n\t\tt.Errorf(\"expected %q, got: %q\", \"linear_interpolation\", s.Type())\n\t}\n}\n\nfunc TestPhraseSuggesterSourceWithCollateQueryString(t *testing.T) {\n\ts := NewPhraseSuggester(\"simple_phrase\").\n\t\tText(\"noble price\").\n\t\tField(\"title.trigram\").\n\t\tSize(1).\n\t\tCandidateGenerator(\n\t\t\tNewDirectCandidateGenerator(\"title.trigram\").\n\t\t\t\tSuggestMode(\"always\").\n\t\t\t\tMinWordLength(1),\n\t\t).\n\t\tCollateQuery(\n\t\t\tNewScriptInline(`{\"match\":{\"{{field_name}}\":\"{{suggestion}}\"}}`),\n\t\t).\n\t\tCollateParams(map[string]interface{}{\"field_name\": \"title\"}).\n\t\tCollatePrune(true)\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"simple_phrase\":{\"text\":\"noble price\",\"phrase\":{\"collate\":{\"params\":{\"field_name\":\"title\"},\"prune\":true,\"query\":{\"source\":{\"match\":{\"{{field_name}}\":\"{{suggestion}}\"}}}},\"direct_generator\":[{\"field\":\"title.trigram\",\"min_word_length\":1,\"suggest_mode\":\"always\"}],\"field\":\"title.trigram\",\"size\":1}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "suggester_term.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\n// TermSuggester suggests terms based on edit distance.\n// For more details, see\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-suggesters-term.html.\ntype TermSuggester struct {\n\tSuggester\n\tname           string\n\ttext           string\n\tfield          string\n\tanalyzer       string\n\tsize           *int\n\tshardSize      *int\n\tcontextQueries []SuggesterContextQuery\n\n\t// fields specific to term suggester\n\tsuggestMode    string\n\taccuracy       *float64\n\tsort           string\n\tstringDistance string\n\tmaxEdits       *int\n\tmaxInspections *int\n\tmaxTermFreq    *float64\n\tprefixLength   *int\n\tminWordLength  *int\n\tminDocFreq     *float64\n}\n\n// NewTermSuggester creates a new TermSuggester.\nfunc NewTermSuggester(name string) *TermSuggester {\n\treturn &TermSuggester{\n\t\tname: name,\n\t}\n}\n\nfunc (q *TermSuggester) Name() string {\n\treturn q.name\n}\n\nfunc (q *TermSuggester) Text(text string) *TermSuggester {\n\tq.text = text\n\treturn q\n}\n\nfunc (q *TermSuggester) Field(field string) *TermSuggester {\n\tq.field = field\n\treturn q\n}\n\nfunc (q *TermSuggester) Analyzer(analyzer string) *TermSuggester {\n\tq.analyzer = analyzer\n\treturn q\n}\n\nfunc (q *TermSuggester) Size(size int) *TermSuggester {\n\tq.size = &size\n\treturn q\n}\n\nfunc (q *TermSuggester) ShardSize(shardSize int) *TermSuggester {\n\tq.shardSize = &shardSize\n\treturn q\n}\n\nfunc (q *TermSuggester) ContextQuery(query SuggesterContextQuery) *TermSuggester {\n\tq.contextQueries = append(q.contextQueries, query)\n\treturn q\n}\n\nfunc (q *TermSuggester) ContextQueries(queries ...SuggesterContextQuery) *TermSuggester {\n\tq.contextQueries = append(q.contextQueries, queries...)\n\treturn q\n}\n\nfunc (q *TermSuggester) SuggestMode(suggestMode string) *TermSuggester {\n\tq.suggestMode = suggestMode\n\treturn q\n}\n\nfunc (q *TermSuggester) Accuracy(accuracy float64) *TermSuggester {\n\tq.accuracy = &accuracy\n\treturn q\n}\n\nfunc (q *TermSuggester) Sort(sort string) *TermSuggester {\n\tq.sort = sort\n\treturn q\n}\n\nfunc (q *TermSuggester) StringDistance(stringDistance string) *TermSuggester {\n\tq.stringDistance = stringDistance\n\treturn q\n}\n\nfunc (q *TermSuggester) MaxEdits(maxEdits int) *TermSuggester {\n\tq.maxEdits = &maxEdits\n\treturn q\n}\n\nfunc (q *TermSuggester) MaxInspections(maxInspections int) *TermSuggester {\n\tq.maxInspections = &maxInspections\n\treturn q\n}\n\nfunc (q *TermSuggester) MaxTermFreq(maxTermFreq float64) *TermSuggester {\n\tq.maxTermFreq = &maxTermFreq\n\treturn q\n}\n\nfunc (q *TermSuggester) PrefixLength(prefixLength int) *TermSuggester {\n\tq.prefixLength = &prefixLength\n\treturn q\n}\n\nfunc (q *TermSuggester) MinWordLength(minWordLength int) *TermSuggester {\n\tq.minWordLength = &minWordLength\n\treturn q\n}\n\nfunc (q *TermSuggester) MinDocFreq(minDocFreq float64) *TermSuggester {\n\tq.minDocFreq = &minDocFreq\n\treturn q\n}\n\n// termSuggesterRequest is necessary because the order in which\n// the JSON elements are routed to Elasticsearch is relevant.\n// We got into trouble when using plain maps because the text element\n// needs to go before the term element.\ntype termSuggesterRequest struct {\n\tText string      `json:\"text\"`\n\tTerm interface{} `json:\"term\"`\n}\n\n// Source generates the source for the term suggester.\nfunc (q *TermSuggester) Source(includeName bool) (interface{}, error) {\n\t// \"suggest\" : {\n\t//   \"my-suggest-1\" : {\n\t//     \"text\" : \"the amsterdma meetpu\",\n\t//     \"term\" : {\n\t//       \"field\" : \"body\"\n\t//     }\n\t//   },\n\t//   \"my-suggest-2\" : {\n\t//     \"text\" : \"the rottredam meetpu\",\n\t//     \"term\" : {\n\t//       \"field\" : \"title\",\n\t//     }\n\t//   }\n\t// }\n\tts := &termSuggesterRequest{}\n\tif q.text != \"\" {\n\t\tts.Text = q.text\n\t}\n\n\tsuggester := make(map[string]interface{})\n\tts.Term = suggester\n\n\tif q.analyzer != \"\" {\n\t\tsuggester[\"analyzer\"] = q.analyzer\n\t}\n\tif q.field != \"\" {\n\t\tsuggester[\"field\"] = q.field\n\t}\n\tif q.size != nil {\n\t\tsuggester[\"size\"] = *q.size\n\t}\n\tif q.shardSize != nil {\n\t\tsuggester[\"shard_size\"] = *q.shardSize\n\t}\n\tswitch len(q.contextQueries) {\n\tcase 0:\n\tcase 1:\n\t\tsrc, err := q.contextQueries[0].Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsuggester[\"contexts\"] = src\n\tdefault:\n\t\tctxq := make([]interface{}, len(q.contextQueries))\n\t\tfor i, query := range q.contextQueries {\n\t\t\tsrc, err := query.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tctxq[i] = src\n\t\t}\n\t\tsuggester[\"contexts\"] = ctxq\n\t}\n\n\t// Specific to term suggester\n\tif q.suggestMode != \"\" {\n\t\tsuggester[\"suggest_mode\"] = q.suggestMode\n\t}\n\tif q.accuracy != nil {\n\t\tsuggester[\"accuracy\"] = *q.accuracy\n\t}\n\tif q.sort != \"\" {\n\t\tsuggester[\"sort\"] = q.sort\n\t}\n\tif q.stringDistance != \"\" {\n\t\tsuggester[\"string_distance\"] = q.stringDistance\n\t}\n\tif q.maxEdits != nil {\n\t\tsuggester[\"max_edits\"] = *q.maxEdits\n\t}\n\tif q.maxInspections != nil {\n\t\tsuggester[\"max_inspections\"] = *q.maxInspections\n\t}\n\tif q.maxTermFreq != nil {\n\t\tsuggester[\"max_term_freq\"] = *q.maxTermFreq\n\t}\n\tif q.prefixLength != nil {\n\t\tsuggester[\"prefix_length\"] = *q.prefixLength\n\t}\n\tif q.minWordLength != nil {\n\t\tsuggester[\"min_word_length\"] = *q.minWordLength\n\t}\n\tif q.minDocFreq != nil {\n\t\tsuggester[\"min_doc_freq\"] = *q.minDocFreq\n\t}\n\n\tif !includeName {\n\t\treturn ts, nil\n\t}\n\n\tsource := make(map[string]interface{})\n\tsource[q.name] = ts\n\treturn source, nil\n}\n"
  },
  {
    "path": "suggester_term_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestTermSuggesterSource(t *testing.T) {\n\ts := NewTermSuggester(\"name\").\n\t\tText(\"n\").\n\t\tField(\"suggest\")\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"name\":{\"text\":\"n\",\"term\":{\"field\":\"suggest\"}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestTermSuggesterWithPrefixLengthSource(t *testing.T) {\n\ts := NewTermSuggester(\"name\").\n\t\tText(\"n\").\n\t\tField(\"suggest\").\n\t\tPrefixLength(0)\n\tsrc, err := s.Source(true)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdata, err := json.Marshal(src)\n\tif err != nil {\n\t\tt.Fatalf(\"marshaling to JSON failed: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"name\":{\"text\":\"n\",\"term\":{\"field\":\"suggest\",\"prefix_length\":0}}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\n,got:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "tasks_cancel.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// TasksCancelService can cancel long-running tasks.\n// It is supported as of Elasticsearch 2.3.0.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/tasks.html#task-cancellation\n// for details.\ntype TasksCancelService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\ttaskId       string\n\tactions      []string\n\tnodeId       []string\n\tparentTaskId string\n}\n\n// NewTasksCancelService creates a new TasksCancelService.\nfunc NewTasksCancelService(client *Client) *TasksCancelService {\n\treturn &TasksCancelService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *TasksCancelService) Pretty(pretty bool) *TasksCancelService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *TasksCancelService) Human(human bool) *TasksCancelService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *TasksCancelService) ErrorTrace(errorTrace bool) *TasksCancelService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *TasksCancelService) FilterPath(filterPath ...string) *TasksCancelService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *TasksCancelService) Header(name string, value string) *TasksCancelService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *TasksCancelService) Headers(headers http.Header) *TasksCancelService {\n\ts.headers = headers\n\treturn s\n}\n\n// TaskId specifies the task to cancel. Notice that the caller is responsible\n// for using the correct format, i.e. node_id:task_number, as specified in\n// the REST API.\nfunc (s *TasksCancelService) TaskId(taskId string) *TasksCancelService {\n\ts.taskId = taskId\n\treturn s\n}\n\n// TaskIdFromNodeAndId specifies the task to cancel. Set id to -1 for all tasks.\nfunc (s *TasksCancelService) TaskIdFromNodeAndId(nodeId string, id int64) *TasksCancelService {\n\tif id != -1 {\n\t\ts.taskId = fmt.Sprintf(\"%s:%d\", nodeId, id)\n\t}\n\treturn s\n}\n\n// Actions is a list of actions that should be cancelled. Leave empty to cancel all.\nfunc (s *TasksCancelService) Actions(actions ...string) *TasksCancelService {\n\ts.actions = append(s.actions, actions...)\n\treturn s\n}\n\n// NodeId is a list of node IDs or names to limit the returned information;\n// use `_local` to return information from the node you're connecting to,\n// leave empty to get information from all nodes.\nfunc (s *TasksCancelService) NodeId(nodeId ...string) *TasksCancelService {\n\ts.nodeId = append(s.nodeId, nodeId...)\n\treturn s\n}\n\n// ParentTaskId specifies to cancel tasks with specified parent task id.\n// Notice that the caller is responsible for using the correct format,\n// i.e. node_id:task_number, as specified in the REST API.\nfunc (s *TasksCancelService) ParentTaskId(parentTaskId string) *TasksCancelService {\n\ts.parentTaskId = parentTaskId\n\treturn s\n}\n\n// ParentTaskIdFromNodeAndId specifies to cancel tasks with specified parent task id.\nfunc (s *TasksCancelService) ParentTaskIdFromNodeAndId(nodeId string, id int64) *TasksCancelService {\n\tif id != -1 {\n\t\ts.parentTaskId = fmt.Sprintf(\"%s:%d\", nodeId, id)\n\t}\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *TasksCancelService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif s.taskId != \"\" {\n\t\tpath, err = uritemplates.Expand(\"/_tasks/{task_id}/_cancel\", map[string]string{\n\t\t\t\"task_id\": s.taskId,\n\t\t})\n\t} else {\n\t\tpath = \"/_tasks/_cancel\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif len(s.actions) > 0 {\n\t\tparams.Set(\"actions\", strings.Join(s.actions, \",\"))\n\t}\n\tif len(s.nodeId) > 0 {\n\t\tparams.Set(\"nodes\", strings.Join(s.nodeId, \",\"))\n\t}\n\tif s.parentTaskId != \"\" {\n\t\tparams.Set(\"parent_task_id\", s.parentTaskId)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *TasksCancelService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *TasksCancelService) Do(ctx context.Context) (*TasksListResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(TasksListResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n"
  },
  {
    "path": "tasks_cancel_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestTasksCancelBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// Cancel all\n\tgot, _, err := client.TasksCancel().buildURL()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant := \"/_tasks/_cancel\"\n\tif got != want {\n\t\tt.Errorf(\"want %q; got %q\", want, got)\n\t}\n\n\t// Cancel all with empty TaskId\n\tgot, _, err = client.TasksCancel().TaskId(\"\").buildURL()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant = \"/_tasks/_cancel\"\n\tif got != want {\n\t\tt.Errorf(\"want %q; got %q\", want, got)\n\t}\n\n\t// Cancel all with invalid TaskId\n\tgot, _, err = client.TasksCancel().TaskId(\"invalid\").buildURL()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant = \"/_tasks/invalid/_cancel\"\n\tif got != want {\n\t\tt.Errorf(\"want %q; got %q\", want, got)\n\t}\n\n\t// Cancel all with id set to -1\n\tgot, _, err = client.TasksCancel().TaskIdFromNodeAndId(\"\", -1).buildURL()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant = \"/_tasks/_cancel\"\n\tif got != want {\n\t\tt.Errorf(\"want %q; got %q\", want, got)\n\t}\n\n\t// Cancel specific task\n\tgot, _, err = client.TasksCancel().TaskIdFromNodeAndId(\"abc\", 42).buildURL()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant = \"/_tasks/abc%3A42/_cancel\"\n\tif got != want {\n\t\tt.Errorf(\"want %q; got %q\", want, got)\n\t}\n}\n\n/*\nfunc TestTasksCancel(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t)\n\tesversion, err := client.ElasticsearchVersion(DefaultURL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif esversion < \"2.3.0\" {\n\t\tt.Skipf(\"Elasticsearch %v does not support Tasks Management API yet\", esversion)\n\t}\n\tres, err := client.TasksCancel(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"response is nil\")\n\t}\n}\n*/\n"
  },
  {
    "path": "tasks_get_task.go",
    "content": "package elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// TasksGetTaskService retrieves the state of a task in the cluster. It is part of the Task Management API\n// documented at https://www.elastic.co/guide/en/elasticsearch/reference/7.0/tasks.html#_current_tasks_information.\ntype TasksGetTaskService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\ttaskId            string\n\twaitForCompletion *bool\n}\n\n// NewTasksGetTaskService creates a new TasksGetTaskService.\nfunc NewTasksGetTaskService(client *Client) *TasksGetTaskService {\n\treturn &TasksGetTaskService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *TasksGetTaskService) Pretty(pretty bool) *TasksGetTaskService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *TasksGetTaskService) Human(human bool) *TasksGetTaskService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *TasksGetTaskService) ErrorTrace(errorTrace bool) *TasksGetTaskService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *TasksGetTaskService) FilterPath(filterPath ...string) *TasksGetTaskService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *TasksGetTaskService) Header(name string, value string) *TasksGetTaskService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *TasksGetTaskService) Headers(headers http.Header) *TasksGetTaskService {\n\ts.headers = headers\n\treturn s\n}\n\n// TaskId specifies the task to return. Notice that the caller is responsible\n// for using the correct format, i.e. node_id:task_number, as specified in\n// the REST API.\nfunc (s *TasksGetTaskService) TaskId(taskId string) *TasksGetTaskService {\n\ts.taskId = taskId\n\treturn s\n}\n\n// TaskIdFromNodeAndId indicates to return the task on the given node with specified id.\nfunc (s *TasksGetTaskService) TaskIdFromNodeAndId(nodeId string, id int64) *TasksGetTaskService {\n\ts.taskId = fmt.Sprintf(\"%s:%d\", nodeId, id)\n\treturn s\n}\n\n// WaitForCompletion indicates whether to wait for the matching tasks\n// to complete (default: false).\nfunc (s *TasksGetTaskService) WaitForCompletion(waitForCompletion bool) *TasksGetTaskService {\n\ts.waitForCompletion = &waitForCompletion\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *TasksGetTaskService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_tasks/{task_id}\", map[string]string{\n\t\t\"task_id\": s.taskId,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.waitForCompletion; v != nil {\n\t\tparams.Set(\"wait_for_completion\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *TasksGetTaskService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *TasksGetTaskService) Do(ctx context.Context) (*TasksGetTaskResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(TasksGetTaskResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\tret.Header = res.Header\n\treturn ret, nil\n}\n\ntype TasksGetTaskResponse struct {\n\tHeader    http.Header   `json:\"-\"`\n\tCompleted bool          `json:\"completed\"`\n\tTask      *TaskInfo     `json:\"task,omitempty\"`\n\tError     *ErrorDetails `json:\"error,omitempty\"`\n}\n"
  },
  {
    "path": "tasks_get_task_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestTasksGetTaskBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\t// Get specific task\n\tgot, _, err := client.TasksGetTask().TaskId(\"node1:123\").buildURL()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant := \"/_tasks/node1%3A123\"\n\tif got != want {\n\t\tt.Errorf(\"want %q; got %q\", want, got)\n\t}\n\n\t// Get specific task\n\tgot, _, err = client.TasksGetTask().TaskIdFromNodeAndId(\"node2\", 678).buildURL()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twant = \"/_tasks/node2%3A678\"\n\tif got != want {\n\t\tt.Errorf(\"want %q; got %q\", want, got)\n\t}\n}\n\nfunc TestTasksGetTask(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Create a reindexing task\n\tvar taskID string\n\t{\n\t\tres, err := client.Reindex().\n\t\t\tSourceIndex(testIndexName).\n\t\t\tDestinationIndex(testIndexName4).\n\t\t\tDoAsync(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"unable to start reindexing task: %v\", err)\n\t\t}\n\t\ttaskID = res.TaskId\n\t}\n\n\t// Get the task by ID\n\tres, err := client.TasksGetTask().\n\t\tTaskId(taskID).\n\t\tHeader(\"X-Opaque-Id\", \"987654\").\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"response is nil\")\n\t}\n\tif want, have := \"987654\", res.Header.Get(\"X-Opaque-Id\"); want != have {\n\t\tt.Fatalf(\"expected HTTP header %#v; got: %#v\", want, have)\n\t}\n\tif res.Task == nil {\n\t\tt.Fatal(\"task is nil\")\n\t}\n\t// Elasticsearch <= 6.4.1 doesn't return the X-Opaque-Id in the body,\n\t// only in response header.\n\t/*\n\t\thave, found := res.Task.Headers[\"X-Opaque-Id\"]\n\t\tif !found {\n\t\t\tt.Fatalf(\"expected to find headers[%q]\", \"X-Opaque-Id\")\n\t\t}\n\t\tif want := \"987654\"; want != have {\n\t\t\tt.Fatalf(\"expected headers[%q]=%q; got: %q\", \"X-Opaque-Id\", want, have)\n\t\t}\n\t*/\n}\n\nfunc TestTasksGetTaskWithError(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Create a reindexing task\n\tvar taskID string\n\t{\n\t\tres, err := client.UpdateByQuery(testIndexName).\n\t\t\tWaitForCompletion(false).\n\t\t\tConflicts(\"proceed\").\n\t\t\tScript(NewScript(\"kaboom\")).\n\t\t\tDoAsync(context.Background())\n\t\tif err != nil {\n\t\t\tt.Fatalf(\"unable to start update_by_query task: %v\", err)\n\t\t}\n\t\ttaskID = res.TaskId\n\t}\n\n\tvar (\n\t\tresponse *TasksGetTaskResponse\n\t\tlastErr  error\n\t)\n\tdone := make(chan struct{}, 1)\n\tgo func() {\n\t\tdefer close(done)\n\t\tfor {\n\t\t\t// Get the task by ID\n\t\t\tres, err := client.TasksGetTask().\n\t\t\t\tTaskId(taskID).\n\t\t\t\tDo(context.Background())\n\t\t\tif err != nil {\n\t\t\t\tlastErr = err\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif res == nil {\n\t\t\t\tlastErr = errors.New(\"response is nil\")\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif res.Completed {\n\t\t\t\tlastErr = nil\n\t\t\t\tresponse = res\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttime.Sleep(1 * time.Second) // retry\n\t\t}\n\t}()\n\n\tselect {\n\tcase <-done:\n\tcase <-time.After(5 * time.Second):\n\t\tt.Fatal(\"expected to finish the task after 5 seconds\")\n\t}\n\tif lastErr != nil {\n\t\tt.Fatalf(\"expected no error, got %v\", lastErr)\n\t}\n\tif response == nil {\n\t\tt.Fatal(\"expected a response, got nil\")\n\t}\n\tif response.Error == nil {\n\t\tt.Fatal(\"expected a response with an error, got nil\")\n\t}\n\tif want, have := \"script_exception\", response.Error.Type; want != have {\n\t\tt.Fatalf(\"expected an error type of %q, got %q\", want, have)\n\t}\n}\n"
  },
  {
    "path": "tasks_list.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// TasksListService retrieves the list of currently executing tasks\n// on one ore more nodes in the cluster. It is part of the Task Management API\n// documented at https://www.elastic.co/guide/en/elasticsearch/reference/7.0/tasks.html.\n//\n// It is supported as of Elasticsearch 2.3.0.\ntype TasksListService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\ttaskId            []string\n\tactions           []string\n\tdetailed          *bool\n\tnodeId            []string\n\tparentTaskId      string\n\twaitForCompletion *bool\n\tgroupBy           string\n}\n\n// NewTasksListService creates a new TasksListService.\nfunc NewTasksListService(client *Client) *TasksListService {\n\treturn &TasksListService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *TasksListService) Pretty(pretty bool) *TasksListService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *TasksListService) Human(human bool) *TasksListService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *TasksListService) ErrorTrace(errorTrace bool) *TasksListService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *TasksListService) FilterPath(filterPath ...string) *TasksListService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *TasksListService) Header(name string, value string) *TasksListService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *TasksListService) Headers(headers http.Header) *TasksListService {\n\ts.headers = headers\n\treturn s\n}\n\n// TaskId indicates to returns the task(s) with specified id(s).\n// Notice that the caller is responsible for using the correct format,\n// i.e. node_id:task_number, as specified in the REST API.\nfunc (s *TasksListService) TaskId(taskId ...string) *TasksListService {\n\ts.taskId = append(s.taskId, taskId...)\n\treturn s\n}\n\n// Actions is a list of actions that should be returned. Leave empty to return all.\nfunc (s *TasksListService) Actions(actions ...string) *TasksListService {\n\ts.actions = append(s.actions, actions...)\n\treturn s\n}\n\n// Detailed indicates whether to return detailed task information (default: false).\nfunc (s *TasksListService) Detailed(detailed bool) *TasksListService {\n\ts.detailed = &detailed\n\treturn s\n}\n\n// NodeId is a list of node IDs or names to limit the returned information;\n// use `_local` to return information from the node you're connecting to,\n// leave empty to get information from all nodes.\nfunc (s *TasksListService) NodeId(nodeId ...string) *TasksListService {\n\ts.nodeId = append(s.nodeId, nodeId...)\n\treturn s\n}\n\n// ParentTaskId returns tasks with specified parent task id.\n// Notice that the caller is responsible for using the correct format,\n// i.e. node_id:task_number, as specified in the REST API.\nfunc (s *TasksListService) ParentTaskId(parentTaskId string) *TasksListService {\n\ts.parentTaskId = parentTaskId\n\treturn s\n}\n\n// WaitForCompletion indicates whether to wait for the matching tasks\n// to complete (default: false).\nfunc (s *TasksListService) WaitForCompletion(waitForCompletion bool) *TasksListService {\n\ts.waitForCompletion = &waitForCompletion\n\treturn s\n}\n\n// GroupBy groups tasks by nodes or parent/child relationships.\n// As of now, it can either be \"nodes\" (default) or \"parents\" or \"none\".\nfunc (s *TasksListService) GroupBy(groupBy string) *TasksListService {\n\ts.groupBy = groupBy\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *TasksListService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.taskId) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_tasks/{task_id}\", map[string]string{\n\t\t\t\"task_id\": strings.Join(s.taskId, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_tasks\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif len(s.actions) > 0 {\n\t\tparams.Set(\"actions\", strings.Join(s.actions, \",\"))\n\t}\n\tif v := s.detailed; v != nil {\n\t\tparams.Set(\"detailed\", fmt.Sprint(*v))\n\t}\n\tif len(s.nodeId) > 0 {\n\t\tparams.Set(\"nodes\", strings.Join(s.nodeId, \",\"))\n\t}\n\tif s.parentTaskId != \"\" {\n\t\tparams.Set(\"parent_task_id\", s.parentTaskId)\n\t}\n\tif v := s.waitForCompletion; v != nil {\n\t\tparams.Set(\"wait_for_completion\", fmt.Sprint(*v))\n\t}\n\tif s.groupBy != \"\" {\n\t\tparams.Set(\"group_by\", s.groupBy)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *TasksListService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *TasksListService) Do(ctx context.Context) (*TasksListResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(TasksListResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\tret.Header = res.Header\n\treturn ret, nil\n}\n\n// TasksListResponse is the response of TasksListService.Do.\ntype TasksListResponse struct {\n\tHeader       http.Header             `json:\"-\"`\n\tTaskFailures []*TaskOperationFailure `json:\"task_failures\"`\n\tNodeFailures []*FailedNodeException  `json:\"node_failures\"`\n\t// Nodes returns the tasks per node. The key is the node id.\n\tNodes map[string]*DiscoveryNode `json:\"nodes\"`\n}\n\ntype TaskOperationFailure struct {\n\tTaskId int64         `json:\"task_id\"` // this is a long in the Java source\n\tNodeId string        `json:\"node_id\"`\n\tStatus string        `json:\"status\"`\n\tReason *ErrorDetails `json:\"reason\"`\n}\n\ntype DiscoveryNode struct {\n\tName             string                 `json:\"name\"`\n\tTransportAddress string                 `json:\"transport_address\"`\n\tHost             string                 `json:\"host\"`\n\tIP               string                 `json:\"ip\"`\n\tRoles            []string               `json:\"roles\"` // \"master\", \"data\", or \"ingest\"\n\tAttributes       map[string]interface{} `json:\"attributes\"`\n\t// Tasks returns the tasks by its id (as a string).\n\tTasks map[string]*TaskInfo `json:\"tasks\"`\n}\n\n// TaskInfo represents information about a currently running task.\ntype TaskInfo struct {\n\tNode               string            `json:\"node\"`\n\tId                 int64             `json:\"id\"` // the task id (yes, this is a long in the Java source)\n\tType               string            `json:\"type\"`\n\tAction             string            `json:\"action\"`\n\tStatus             interface{}       `json:\"status\"`      // has separate implementations of Task.Status in Java for reindexing, replication, and \"RawTaskStatus\"\n\tDescription        interface{}       `json:\"description\"` // same as Status\n\tStartTime          string            `json:\"start_time\"`\n\tStartTimeInMillis  int64             `json:\"start_time_in_millis\"`\n\tRunningTime        string            `json:\"running_time\"`\n\tRunningTimeInNanos int64             `json:\"running_time_in_nanos\"`\n\tCancellable        bool              `json:\"cancellable\"`\n\tCancelled          bool              `json:\"cancelled\"`\n\tParentTaskId       string            `json:\"parent_task_id\"` // like \"YxJnVYjwSBm_AUbzddTajQ:12356\"\n\tHeaders            map[string]string `json:\"headers\"`\n}\n\n// StartTaskResult is used in cases where a task gets started asynchronously and\n// the operation simply returnes a TaskID to watch for via the Task Management API.\ntype StartTaskResult struct {\n\tHeader http.Header `json:\"-\"`\n\tTaskId string      `json:\"task\"`\n}\n"
  },
  {
    "path": "tasks_list_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestTasksListBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tTaskId   []string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\tTaskId:   []string{},\n\t\t\tExpected: \"/_tasks\",\n\t\t},\n\t\t{\n\t\t\tTaskId:   []string{\"node1:42\"},\n\t\t\tExpected: \"/_tasks/node1%3A42\",\n\t\t},\n\t\t{\n\t\t\tTaskId:   []string{\"node1:42\", \"node2:37\"},\n\t\t\tExpected: \"/_tasks/node1%3A42%2Cnode2%3A37\",\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tpath, _, err := client.TasksList().\n\t\t\tTaskId(tt.TaskId...).\n\t\t\tbuildURL()\n\t\tif err != nil {\n\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\tcontinue\n\t\t}\n\t\tif path != tt.Expected {\n\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, tt.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestTasksList(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tres, err := client.TasksList().\n\t\tPretty(true).\n\t\tHuman(true).\n\t\tHeader(\"X-Opaque-Id\", \"123456\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"response is nil\")\n\t}\n\tif len(res.Nodes) == 0 {\n\t\tt.Fatalf(\"expected at least 1 node; got: %d\", len(res.Nodes))\n\t}\n\tif want, have := \"123456\", res.Header.Get(\"X-Opaque-Id\"); want != have {\n\t\tt.Fatalf(\"expected HTTP header %#v; got: %#v\", want, have)\n\t}\n\tfor _, node := range res.Nodes {\n\t\tif len(node.Tasks) == 0 {\n\t\t\tt.Fatalf(\"expected at least 1 task; got: %d\", len(node.Tasks))\n\t\t}\n\t\tfor _, task := range node.Tasks {\n\t\t\thave, found := task.Headers[\"X-Opaque-Id\"]\n\t\t\tif !found {\n\t\t\t\tt.Logf(\"flaky test: expected to find headers[%q]\", \"X-Opaque-Id\")\n\t\t\t} else if want := \"123456\"; want != have {\n\t\t\t\tt.Fatalf(\"expected headers[%q]=%q; got: %q\", \"X-Opaque-Id\", want, have)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "termvectors.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// TermvectorsService returns information and statistics on terms in the\n// fields of a particular document. The document could be stored in the\n// index or artificially provided by the user.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-termvectors.html\n// for documentation.\ntype TermvectorsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid               string\n\tindex            string\n\ttyp              string\n\tdfs              *bool\n\tdoc              interface{}\n\tfieldStatistics  *bool\n\tfields           []string\n\tfilter           *TermvectorsFilterSettings\n\tperFieldAnalyzer map[string]string\n\toffsets          *bool\n\tparent           string\n\tpayloads         *bool\n\tpositions        *bool\n\tpreference       string\n\trealtime         *bool\n\trouting          string\n\ttermStatistics   *bool\n\tversion          interface{}\n\tversionType      string\n\tbodyJson         interface{}\n\tbodyString       string\n}\n\n// NewTermvectorsService creates a new TermvectorsService.\nfunc NewTermvectorsService(client *Client) *TermvectorsService {\n\treturn &TermvectorsService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *TermvectorsService) Pretty(pretty bool) *TermvectorsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *TermvectorsService) Human(human bool) *TermvectorsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *TermvectorsService) ErrorTrace(errorTrace bool) *TermvectorsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *TermvectorsService) FilterPath(filterPath ...string) *TermvectorsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *TermvectorsService) Header(name string, value string) *TermvectorsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *TermvectorsService) Headers(headers http.Header) *TermvectorsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index in which the document resides.\nfunc (s *TermvectorsService) Index(index string) *TermvectorsService {\n\ts.index = index\n\treturn s\n}\n\n// Type of the document.\n//\n// Deprecated: Types are in the process of being removed.\nfunc (s *TermvectorsService) Type(typ string) *TermvectorsService {\n\ts.typ = typ\n\treturn s\n}\n\n// Id of the document.\nfunc (s *TermvectorsService) Id(id string) *TermvectorsService {\n\ts.id = id\n\treturn s\n}\n\n// Dfs specifies if distributed frequencies should be returned instead\n// shard frequencies.\nfunc (s *TermvectorsService) Dfs(dfs bool) *TermvectorsService {\n\ts.dfs = &dfs\n\treturn s\n}\n\n// Doc is the document to analyze.\nfunc (s *TermvectorsService) Doc(doc interface{}) *TermvectorsService {\n\ts.doc = doc\n\treturn s\n}\n\n// FieldStatistics specifies if document count, sum of document frequencies\n// and sum of total term frequencies should be returned.\nfunc (s *TermvectorsService) FieldStatistics(fieldStatistics bool) *TermvectorsService {\n\ts.fieldStatistics = &fieldStatistics\n\treturn s\n}\n\n// Fields a list of fields to return.\nfunc (s *TermvectorsService) Fields(fields ...string) *TermvectorsService {\n\tif s.fields == nil {\n\t\ts.fields = make([]string, 0)\n\t}\n\ts.fields = append(s.fields, fields...)\n\treturn s\n}\n\n// Filter adds terms filter settings.\nfunc (s *TermvectorsService) Filter(filter *TermvectorsFilterSettings) *TermvectorsService {\n\ts.filter = filter\n\treturn s\n}\n\n// PerFieldAnalyzer allows to specify a different analyzer than the one\n// at the field.\nfunc (s *TermvectorsService) PerFieldAnalyzer(perFieldAnalyzer map[string]string) *TermvectorsService {\n\ts.perFieldAnalyzer = perFieldAnalyzer\n\treturn s\n}\n\n// Offsets specifies if term offsets should be returned.\nfunc (s *TermvectorsService) Offsets(offsets bool) *TermvectorsService {\n\ts.offsets = &offsets\n\treturn s\n}\n\n// Parent id of documents.\nfunc (s *TermvectorsService) Parent(parent string) *TermvectorsService {\n\ts.parent = parent\n\treturn s\n}\n\n// Payloads specifies if term payloads should be returned.\nfunc (s *TermvectorsService) Payloads(payloads bool) *TermvectorsService {\n\ts.payloads = &payloads\n\treturn s\n}\n\n// Positions specifies if term positions should be returned.\nfunc (s *TermvectorsService) Positions(positions bool) *TermvectorsService {\n\ts.positions = &positions\n\treturn s\n}\n\n// Preference specify the node or shard the operation\n// should be performed on (default: random).\nfunc (s *TermvectorsService) Preference(preference string) *TermvectorsService {\n\ts.preference = preference\n\treturn s\n}\n\n// Realtime specifies if request is real-time as opposed to\n// near-real-time (default: true).\nfunc (s *TermvectorsService) Realtime(realtime bool) *TermvectorsService {\n\ts.realtime = &realtime\n\treturn s\n}\n\n// Routing is a specific routing value.\nfunc (s *TermvectorsService) Routing(routing string) *TermvectorsService {\n\ts.routing = routing\n\treturn s\n}\n\n// TermStatistics specifies if total term frequency and document frequency\n// should be returned.\nfunc (s *TermvectorsService) TermStatistics(termStatistics bool) *TermvectorsService {\n\ts.termStatistics = &termStatistics\n\treturn s\n}\n\n// Version an explicit version number for concurrency control.\nfunc (s *TermvectorsService) Version(version interface{}) *TermvectorsService {\n\ts.version = version\n\treturn s\n}\n\n// VersionType specifies a version type (\"internal\", \"external\", or \"external_gte\").\nfunc (s *TermvectorsService) VersionType(versionType string) *TermvectorsService {\n\ts.versionType = versionType\n\treturn s\n}\n\n// BodyJson defines the body parameters. See documentation.\nfunc (s *TermvectorsService) BodyJson(body interface{}) *TermvectorsService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString defines the body parameters as a string. See documentation.\nfunc (s *TermvectorsService) BodyString(body string) *TermvectorsService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *TermvectorsService) buildURL() (string, url.Values, error) {\n\tvar pathParam = map[string]string{\n\t\t\"index\": s.index,\n\t}\n\tpath := \"/{index}\"\n\tvar err error\n\n\tif s.typ != \"\" {\n\t\tpathParam[\"type\"] = s.typ\n\t\tpath += \"/{type}\"\n\t} else {\n\t\tpath += \"/_termvectors\"\n\t}\n\tif s.id != \"\" {\n\t\tpathParam[\"id\"] = s.id\n\t\tpath += \"/{id}\"\n\t}\n\tif s.typ != \"\" {\n\t\tpath += \"/_termvectors\"\n\t}\n\n\tpath, err = uritemplates.Expand(path, pathParam)\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.dfs; v != nil {\n\t\tparams.Set(\"dfs\", fmt.Sprint(*v))\n\t}\n\tif v := s.fieldStatistics; v != nil {\n\t\tparams.Set(\"field_statistics\", fmt.Sprint(*v))\n\t}\n\tif len(s.fields) > 0 {\n\t\tparams.Set(\"fields\", strings.Join(s.fields, \",\"))\n\t}\n\tif v := s.offsets; v != nil {\n\t\tparams.Set(\"offsets\", fmt.Sprint(*v))\n\t}\n\tif s.parent != \"\" {\n\t\tparams.Set(\"parent\", s.parent)\n\t}\n\tif v := s.payloads; v != nil {\n\t\tparams.Set(\"payloads\", fmt.Sprint(*v))\n\t}\n\tif v := s.positions; v != nil {\n\t\tparams.Set(\"positions\", fmt.Sprint(*v))\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif v := s.realtime; v != nil {\n\t\tparams.Set(\"realtime\", fmt.Sprint(*v))\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif v := s.termStatistics; v != nil {\n\t\tparams.Set(\"term_statistics\", fmt.Sprint(*v))\n\t}\n\tif s.version != nil {\n\t\tparams.Set(\"version\", fmt.Sprintf(\"%v\", s.version))\n\t}\n\tif s.versionType != \"\" {\n\t\tparams.Set(\"version_type\", s.versionType)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *TermvectorsService) Validate() error {\n\tvar invalid []string\n\tif s.index == \"\" {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *TermvectorsService) Do(ctx context.Context) (*TermvectorsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else if s.bodyString != \"\" {\n\t\tbody = s.bodyString\n\t} else {\n\t\tdata := make(map[string]interface{})\n\t\tif s.doc != nil {\n\t\t\tdata[\"doc\"] = s.doc\n\t\t}\n\t\tif len(s.perFieldAnalyzer) > 0 {\n\t\t\tdata[\"per_field_analyzer\"] = s.perFieldAnalyzer\n\t\t}\n\t\tif s.filter != nil {\n\t\t\tsrc, err := s.filter.Source()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tdata[\"filter\"] = src\n\t\t}\n\t\tif len(data) > 0 {\n\t\t\tbody = data\n\t\t}\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(TermvectorsResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// -- Filter settings --\n\n// TermvectorsFilterSettings adds additional filters to a Termsvector request.\n// It allows to filter terms based on their tf-idf scores.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-termvectors.html#_terms_filtering\n// for more information.\ntype TermvectorsFilterSettings struct {\n\tmaxNumTerms   *int64\n\tminTermFreq   *int64\n\tmaxTermFreq   *int64\n\tminDocFreq    *int64\n\tmaxDocFreq    *int64\n\tminWordLength *int64\n\tmaxWordLength *int64\n}\n\n// NewTermvectorsFilterSettings creates and initializes a new TermvectorsFilterSettings struct.\nfunc NewTermvectorsFilterSettings() *TermvectorsFilterSettings {\n\treturn &TermvectorsFilterSettings{}\n}\n\n// MaxNumTerms specifies the maximum number of terms the must be returned per field.\nfunc (fs *TermvectorsFilterSettings) MaxNumTerms(value int64) *TermvectorsFilterSettings {\n\tfs.maxNumTerms = &value\n\treturn fs\n}\n\n// MinTermFreq ignores words with less than this frequency in the source doc.\nfunc (fs *TermvectorsFilterSettings) MinTermFreq(value int64) *TermvectorsFilterSettings {\n\tfs.minTermFreq = &value\n\treturn fs\n}\n\n// MaxTermFreq ignores words with more than this frequency in the source doc.\nfunc (fs *TermvectorsFilterSettings) MaxTermFreq(value int64) *TermvectorsFilterSettings {\n\tfs.maxTermFreq = &value\n\treturn fs\n}\n\n// MinDocFreq ignores terms which do not occur in at least this many docs.\nfunc (fs *TermvectorsFilterSettings) MinDocFreq(value int64) *TermvectorsFilterSettings {\n\tfs.minDocFreq = &value\n\treturn fs\n}\n\n// MaxDocFreq ignores terms which occur in more than this many docs.\nfunc (fs *TermvectorsFilterSettings) MaxDocFreq(value int64) *TermvectorsFilterSettings {\n\tfs.maxDocFreq = &value\n\treturn fs\n}\n\n// MinWordLength specifies the minimum word length below which words will be ignored.\nfunc (fs *TermvectorsFilterSettings) MinWordLength(value int64) *TermvectorsFilterSettings {\n\tfs.minWordLength = &value\n\treturn fs\n}\n\n// MaxWordLength specifies the maximum word length above which words will be ignored.\nfunc (fs *TermvectorsFilterSettings) MaxWordLength(value int64) *TermvectorsFilterSettings {\n\tfs.maxWordLength = &value\n\treturn fs\n}\n\n// Source returns JSON for the query.\nfunc (fs *TermvectorsFilterSettings) Source() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\tif fs.maxNumTerms != nil {\n\t\tsource[\"max_num_terms\"] = *fs.maxNumTerms\n\t}\n\tif fs.minTermFreq != nil {\n\t\tsource[\"min_term_freq\"] = *fs.minTermFreq\n\t}\n\tif fs.maxTermFreq != nil {\n\t\tsource[\"max_term_freq\"] = *fs.maxTermFreq\n\t}\n\tif fs.minDocFreq != nil {\n\t\tsource[\"min_doc_freq\"] = *fs.minDocFreq\n\t}\n\tif fs.maxDocFreq != nil {\n\t\tsource[\"max_doc_freq\"] = *fs.maxDocFreq\n\t}\n\tif fs.minWordLength != nil {\n\t\tsource[\"min_word_length\"] = *fs.minWordLength\n\t}\n\tif fs.maxWordLength != nil {\n\t\tsource[\"max_word_length\"] = *fs.maxWordLength\n\t}\n\treturn source, nil\n}\n\n// -- Response types --\n\ntype TokenInfo struct {\n\tStartOffset int64  `json:\"start_offset\"`\n\tEndOffset   int64  `json:\"end_offset\"`\n\tPosition    int64  `json:\"position\"`\n\tPayload     string `json:\"payload\"`\n}\n\ntype TermsInfo struct {\n\tDocFreq  int64       `json:\"doc_freq\"`\n\tScore    float64     `json:\"score\"`\n\tTermFreq int64       `json:\"term_freq\"`\n\tTtf      int64       `json:\"ttf\"`\n\tTokens   []TokenInfo `json:\"tokens\"`\n}\n\ntype FieldStatistics struct {\n\tDocCount   int64 `json:\"doc_count\"`\n\tSumDocFreq int64 `json:\"sum_doc_freq\"`\n\tSumTtf     int64 `json:\"sum_ttf\"`\n}\n\ntype TermVectorsFieldInfo struct {\n\tFieldStatistics FieldStatistics      `json:\"field_statistics\"`\n\tTerms           map[string]TermsInfo `json:\"terms\"`\n}\n\n// TermvectorsResponse is the response of TermvectorsService.Do.\ntype TermvectorsResponse struct {\n\tIndex       string                          `json:\"_index\"`\n\tType        string                          `json:\"_type\"`\n\tId          string                          `json:\"_id,omitempty\"`\n\tVersion     int                             `json:\"_version\"`\n\tFound       bool                            `json:\"found\"`\n\tTook        int64                           `json:\"took\"`\n\tTermVectors map[string]TermVectorsFieldInfo `json:\"term_vectors\"`\n}\n"
  },
  {
    "path": "termvectors_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestTermVectorsBuildURL(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttests := []struct {\n\t\tIndex    string\n\t\tType     string\n\t\tId       string\n\t\tExpected string\n\t}{\n\t\t{\n\t\t\t\"twitter\",\n\t\t\t\"_doc\",\n\t\t\t\"\",\n\t\t\t\"/twitter/_doc/_termvectors\",\n\t\t},\n\t\t{\n\t\t\t\"twitter\",\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\t\"/twitter/_termvectors\",\n\t\t},\n\t\t{\n\t\t\t\"twitter\",\n\t\t\t\"_doc\",\n\t\t\t\"1\",\n\t\t\t\"/twitter/_doc/1/_termvectors\",\n\t\t},\n\t\t{\n\t\t\t\"twitter\",\n\t\t\t\"\",\n\t\t\t\"1\",\n\t\t\t\"/twitter/_termvectors/1\",\n\t\t},\n\t}\n\n\tfor _, test := range tests {\n\t\tbuilder := client.TermVectors(test.Index).Type(test.Type)\n\t\tif test.Id != \"\" {\n\t\t\tbuilder = builder.Id(test.Id)\n\t\t}\n\t\tpath, _, err := builder.buildURL()\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\tif path != test.Expected {\n\t\t\tt.Errorf(\"expected %q; got: %q\", test.Expected, path)\n\t\t}\n\t}\n}\n\nfunc TestTermVectorsWithId(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\n\t// Add a document\n\tindexResult, err := client.Index().\n\t\tIndex(testIndexName).\n\t\tId(\"1\").\n\t\tBodyJson(&tweet1).\n\t\tRefresh(\"true\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indexResult == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", indexResult)\n\t}\n\n\t// TermVectors by specifying ID\n\tfield := \"Message\"\n\tresult, err := client.TermVectors(testIndexName).\n\t\tId(\"1\").\n\t\tFields(field).\n\t\tFieldStatistics(true).\n\t\tTermStatistics(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif result == nil {\n\t\tt.Fatal(\"expected to return information and statistics\")\n\t}\n\tif !result.Found {\n\t\tt.Errorf(\"expected found to be %v; got: %v\", true, result.Found)\n\t}\n}\n\nfunc TestTermVectorsWithDoc(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// Travis lags sometimes\n\tif isCI() {\n\t\ttime.Sleep(2 * time.Second)\n\t}\n\n\t// TermVectors by specifying Doc\n\tvar doc = map[string]interface{}{\n\t\t\"fullname\": \"John Doe\",\n\t\t\"text\":     \"twitter test test test\",\n\t}\n\tvar perFieldAnalyzer = map[string]string{\n\t\t\"fullname\": \"keyword\",\n\t}\n\n\tresult, err := client.TermVectors(testIndexName).\n\t\tDoc(doc).\n\t\tPerFieldAnalyzer(perFieldAnalyzer).\n\t\tFieldStatistics(true).\n\t\tTermStatistics(true).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif result == nil {\n\t\tt.Fatal(\"expected to return information and statistics\")\n\t}\n\tif !result.Found {\n\t\tt.Errorf(\"expected found to be %v; got: %v\", true, result.Found)\n\t}\n}\n\nfunc TestTermVectorsWithFilter(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\t// Travis lags sometimes\n\tif isCI() {\n\t\ttime.Sleep(2 * time.Second)\n\t}\n\n\t// TermVectors by specifying Doc\n\tvar doc = map[string]interface{}{\n\t\t\"fullname\": \"John Doe\",\n\t\t\"text\":     \"twitter test test test\",\n\t}\n\tvar perFieldAnalyzer = map[string]string{\n\t\t\"fullname\": \"keyword\",\n\t}\n\n\tresult, err := client.TermVectors(testIndexName).\n\t\tDoc(doc).\n\t\tPerFieldAnalyzer(perFieldAnalyzer).\n\t\tFieldStatistics(true).\n\t\tTermStatistics(true).\n\t\tFilter(NewTermvectorsFilterSettings().MinTermFreq(1)).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif result == nil {\n\t\tt.Fatal(\"expected to return information and statistics\")\n\t}\n\tif !result.Found {\n\t\tt.Errorf(\"expected found to be %v; got: %v\", true, result.Found)\n\t}\n}\n"
  },
  {
    "path": "trace/opencensus/transport.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage opencensus\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\n\t\"github.com/pkg/errors\"\n\t\"go.opencensus.io/trace\"\n)\n\n// Transport for tracing Elastic operations.\ntype Transport struct {\n\trt                http.RoundTripper\n\tdefaultAttributes []trace.Attribute\n}\n\n// Option signature for specifying options, e.g. WithRoundTripper.\ntype Option func(t *Transport)\n\n// WithRoundTripper specifies the http.RoundTripper to call\n// next after this transport. If it is nil (default), the\n// transport will use http.DefaultTransport.\nfunc WithRoundTripper(rt http.RoundTripper) Option {\n\treturn func(t *Transport) {\n\t\tt.rt = rt\n\t}\n}\n\n// WithDefaultAttributes specifies default attributes to add\n// to each span.\nfunc WithDefaultAttributes(attrs ...trace.Attribute) Option {\n\treturn func(t *Transport) {\n\t\tt.defaultAttributes = attrs\n\t}\n}\n\n// NewTransport specifies a transport that will trace Elastic\n// and report back via OpenTracing.\nfunc NewTransport(opts ...Option) *Transport {\n\tt := &Transport{}\n\tfor _, o := range opts {\n\t\to(t)\n\t}\n\treturn t\n}\n\n// RoundTrip captures the request and starts an OpenTracing span\n// for Elastic PerformRequest operation.\nfunc (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {\n\t_, span := trace.StartSpan(req.Context(), \"elastic:PerformRequest\")\n\tattrs := append([]trace.Attribute(nil), t.defaultAttributes...)\n\tattrs = append(attrs,\n\t\ttrace.StringAttribute(\"Component\", \"github.com/olivere/elastic/v7\"),\n\t\ttrace.StringAttribute(\"Method\", req.Method),\n\t\ttrace.StringAttribute(\"URL\", req.URL.Redacted()),\n\t\ttrace.StringAttribute(\"Hostname\", req.URL.Hostname()),\n\t\ttrace.Int64Attribute(\"Port\", atoi64(req.URL.Port())),\n\t)\n\tspan.AddAttributes(attrs...)\n\n\tvar (\n\t\tresp *http.Response\n\t\terr  error\n\t)\n\tdefer func() {\n\t\tsetSpanStatus(span, err)\n\t\tspan.End()\n\t}()\n\tif t.rt != nil {\n\t\tresp, err = t.rt.RoundTrip(req)\n\t} else {\n\t\tresp, err = http.DefaultTransport.RoundTrip(req)\n\t}\n\treturn resp, err\n}\n\n// See https://github.com/opencensus-integrations/ocsql/blob/master/driver.go#L749\nfunc setSpanStatus(span *trace.Span, err error) {\n\tvar status trace.Status\n\tswitch {\n\tcase err == nil:\n\t\tstatus.Code = trace.StatusCodeOK\n\t\tspan.SetStatus(status)\n\t\treturn\n\tcase err == context.Canceled:\n\t\tstatus.Code = trace.StatusCodeCancelled\n\tcase err == context.DeadlineExceeded:\n\t\tstatus.Code = trace.StatusCodeDeadlineExceeded\n\tcase isConnErr(err):\n\t\tstatus.Code = trace.StatusCodeUnavailable\n\tcase isNotFound(err):\n\t\tstatus.Code = trace.StatusCodeNotFound\n\tcase isConflict(err):\n\t\tstatus.Code = trace.StatusCodeFailedPrecondition\n\tcase isForbidden(err):\n\t\tstatus.Code = trace.StatusCodePermissionDenied\n\tcase isTimeout(err):\n\t\tstatus.Code = trace.StatusCodeResourceExhausted\n\tdefault:\n\t\tstatus.Code = trace.StatusCodeUnknown\n\t}\n\tstatus.Message = err.Error()\n\tspan.SetStatus(status)\n}\n\n// Copied from elastic to prevent cyclic dependencies.\ntype elasticError struct {\n\tStatus  int           `json:\"status\"`\n\tDetails *errorDetails `json:\"error,omitempty\"`\n}\n\n// errorDetails encapsulate error details from Elasticsearch.\n// It is used in e.g. elastic.Error and elastic.BulkResponseItem.\ntype errorDetails struct {\n\tType         string                   `json:\"type\"`\n\tReason       string                   `json:\"reason\"`\n\tResourceType string                   `json:\"resource.type,omitempty\"`\n\tResourceId   string                   `json:\"resource.id,omitempty\"`\n\tIndex        string                   `json:\"index,omitempty\"`\n\tPhase        string                   `json:\"phase,omitempty\"`\n\tGrouped      bool                     `json:\"grouped,omitempty\"`\n\tCausedBy     map[string]interface{}   `json:\"caused_by,omitempty\"`\n\tRootCause    []*errorDetails          `json:\"root_cause,omitempty\"`\n\tFailedShards []map[string]interface{} `json:\"failed_shards,omitempty\"`\n}\n\n// Error returns a string representation of the error.\nfunc (e *elasticError) Error() string {\n\tif e.Details != nil && e.Details.Reason != \"\" {\n\t\treturn fmt.Sprintf(\"elastic: Error %d (%s): %s [type=%s]\", e.Status, http.StatusText(e.Status), e.Details.Reason, e.Details.Type)\n\t}\n\treturn fmt.Sprintf(\"elastic: Error %d (%s)\", e.Status, http.StatusText(e.Status))\n}\n\n// isContextErr returns true if the error is from a context that was canceled or deadline exceeded\nfunc isContextErr(err error) bool {\n\tif err == context.Canceled || err == context.DeadlineExceeded {\n\t\treturn true\n\t}\n\t// This happens e.g. on redirect errors, see https://golang.org/src/net/http/client_test.go#L329\n\tif ue, ok := err.(*url.Error); ok {\n\t\tif ue.Temporary() {\n\t\t\treturn true\n\t\t}\n\t\t// Use of an AWS Signing Transport can result in a wrapped url.Error\n\t\treturn isContextErr(ue.Err)\n\t}\n\treturn false\n}\n\n// isConnErr returns true if the error indicates that Elastic could not\n// find an Elasticsearch host to connect to.\nfunc isConnErr(err error) bool {\n\tif err == nil {\n\t\treturn false\n\t}\n\tif err.Error() == \"no Elasticsearch node available\" {\n\t\treturn true\n\t}\n\tinnerErr := errors.Cause(err)\n\tif innerErr == nil {\n\t\treturn false\n\t}\n\tif innerErr.Error() == \"no Elasticsearch node available\" {\n\t\treturn true\n\t}\n\treturn false\n}\n\n// isNotFound returns true if the given error indicates that Elasticsearch\n// returned HTTP status 404. The err parameter can be of type *elastic.Error,\n// elastic.Error, *http.Response or int (indicating the HTTP status code).\nfunc isNotFound(err interface{}) bool {\n\treturn isStatusCode(err, http.StatusNotFound)\n}\n\n// isTimeout returns true if the given error indicates that Elasticsearch\n// returned HTTP status 408. The err parameter can be of type *elastic.Error,\n// elastic.Error, *http.Response or int (indicating the HTTP status code).\nfunc isTimeout(err interface{}) bool {\n\treturn isStatusCode(err, http.StatusRequestTimeout)\n}\n\n// isConflict returns true if the given error indicates that the Elasticsearch\n// operation resulted in a version conflict. This can occur in operations like\n// `update` or `index` with `op_type=create`. The err parameter can be of\n// type *elastic.Error, elastic.Error, *http.Response or int (indicating the\n// HTTP status code).\nfunc isConflict(err interface{}) bool {\n\treturn isStatusCode(err, http.StatusConflict)\n}\n\n// isForbidden returns true if the given error indicates that Elasticsearch\n// returned HTTP status 403. This happens e.g. due to a missing license.\n// The err parameter can be of type *elastic.Error, elastic.Error,\n// *http.Response or int (indicating the HTTP status code).\nfunc isForbidden(err interface{}) bool {\n\treturn isStatusCode(err, http.StatusForbidden)\n}\n\n// isStatusCode returns true if the given error indicates that the Elasticsearch\n// operation returned the specified HTTP status code. The err parameter can be of\n// type *http.Response, *Error, Error, or int (indicating the HTTP status code).\nfunc isStatusCode(err interface{}, code int) bool {\n\tswitch e := err.(type) {\n\tcase *http.Response:\n\t\treturn e.StatusCode == code\n\tcase *elasticError:\n\t\treturn e.Status == code\n\tcase elasticError:\n\t\treturn e.Status == code\n\tcase int:\n\t\treturn e == code\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "trace/opencensus/transport_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage opencensus\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"go.opencensus.io/trace\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc init() {\n\t// Always sample\n\ttrace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})\n}\n\ntype testExporter struct {\n\tspans []*trace.SpanData\n}\n\nfunc (t *testExporter) ExportSpan(s *trace.SpanData) {\n\tt.spans = append(t.spans, s)\n}\n\nfunc TestTransport(t *testing.T) {\n\tts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tusername, password, ok := r.BasicAuth()\n\t\tif !ok || username != \"alice\" || password != \"secret\" {\n\t\t\tw.WriteHeader(http.StatusForbidden)\n\t\t\treturn\n\t\t}\n\n\t\tswitch r.URL.Path {\n\t\tcase \"/\":\n\t\t\tw.WriteHeader(http.StatusOK)\n\t\t\tfmt.Fprintln(w, `{\n\t\t\t\t\"name\" : \"Qg28M36\",\n\t\t\t\t\"cluster_name\" : \"docker-cluster\",\n\t\t\t\t\"cluster_uuid\" : \"rwHa7BBnRC2h8KoDfCbmuQ\",\n\t\t\t\t\"version\" : {\n\t\t\t\t\t\"number\" : \"6.3.2\",\n\t\t\t\t\t\"build_flavor\" : \"oss\",\n\t\t\t\t\t\"build_type\" : \"tar\",\n\t\t\t\t\t\"build_hash\" : \"053779d\",\n\t\t\t\t\t\"build_date\" : \"2018-07-20T05:20:23.451332Z\",\n\t\t\t\t\t\"build_snapshot\" : false,\n\t\t\t\t\t\"lucene_version\" : \"7.3.1\",\n\t\t\t\t\t\"minimum_wire_compatibility_version\" : \"5.6.0\",\n\t\t\t\t\t\"minimum_index_compatibility_version\" : \"5.0.0\"\n\t\t\t\t},\n\t\t\t\t\"tagline\" : \"You Know, for Search\"\n\t\t\t}`)\n\t\t\treturn\n\t\tdefault:\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t}))\n\tdefer ts.Close()\n\n\t// Register test exporter\n\tvar te testExporter\n\ttrace.RegisterExporter(&te)\n\n\t// Setup a simple transport\n\ttr := NewTransport(\n\t\tWithDefaultAttributes(\n\t\t\ttrace.StringAttribute(\"Opaque-Id\", \"12345\"),\n\t\t),\n\t)\n\thttpClient := &http.Client{\n\t\tTransport: tr,\n\t}\n\n\t// Create a simple Ping request via Elastic\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(ts.URL),\n\t\telastic.SetHttpClient(httpClient),\n\t\telastic.SetHealthcheck(false),\n\t\telastic.SetSniff(false),\n\t\telastic.SetBasicAuth(\"alice\", \"secret\"),\n\t)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, code, err := client.Ping(ts.URL).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := http.StatusOK, code; want != have {\n\t\tt.Fatalf(\"want Status=%d, have %d\", want, have)\n\t}\n\tif want, have := \"You Know, for Search\", res.TagLine; want != have {\n\t\tt.Fatalf(\"want TagLine=%q, have %q\", want, have)\n\t}\n\ttrace.UnregisterExporter(&te)\n\n\t// Check the data written into tracer\n\tspans := te.spans\n\tif want, have := 1, len(spans); want != have {\n\t\tt.Fatalf(\"want %d finished spans, have %d\", want, have)\n\t}\n\tspan := spans[0]\n\n\tif want, have := \"elastic:PerformRequest\", span.Name; want != have {\n\t\tt.Fatalf(\"want Span.Name=%q, have %q\", want, have)\n\t}\n\tif attr, ok := span.Attributes[\"Component\"].(string); !ok {\n\t\tt.Fatalf(\"attribute %q not found\", \"Component\")\n\t} else if want, have := \"github.com/olivere/elastic/v7\", attr; want != have {\n\t\tt.Fatalf(\"want attribute=%q, have %q\", want, have)\n\t}\n\tif attr, ok := span.Attributes[\"Method\"].(string); !ok {\n\t\tt.Fatalf(\"attribute %q not found\", \"Method\")\n\t} else if want, have := \"GET\", attr; want != have {\n\t\tt.Fatalf(\"want attribute=%q, have %q\", want, have)\n\t}\n\tif attr, ok := span.Attributes[\"URL\"].(string); !ok || attr == \"\" {\n\t\tt.Fatalf(\"attribute %q not found\", \"URL\")\n\t} else if strings.Contains(attr, \"alice\") || strings.Contains(attr, \"password\") {\n\t\tt.Fatalf(\"attribute %q contains username and/or password: %s\", \"URL\", attr)\n\t}\n\tif attr, ok := span.Attributes[\"Hostname\"].(string); !ok || attr == \"\" {\n\t\tt.Fatalf(\"attribute %q not found\", \"Hostname\")\n\t}\n\tif port, ok := span.Attributes[\"Port\"].(int64); !ok || port <= 0 {\n\t\tt.Fatalf(\"attribute %q not found\", \"Port\")\n\t}\n\tif attr, ok := span.Attributes[\"Opaque-Id\"].(string); !ok {\n\t\tt.Fatalf(\"attribute %q not found\", \"Opaque-Id\")\n\t} else if want, have := \"12345\", attr; want != have {\n\t\tt.Fatalf(\"want attribute=%q, have %q\", want, have)\n\t}\n}\n"
  },
  {
    "path": "trace/opencensus/util.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage opencensus\n\nimport (\n\t\"strconv\"\n)\n\nfunc atoi64(s string) int64 {\n\ti, _ := strconv.ParseInt(s, 10, 64)\n\treturn i\n}\n"
  },
  {
    "path": "trace/opentelemetry/transport.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage opentelemetry\n\nimport (\n\t\"net/http\"\n\n\t\"go.opentelemetry.io/otel\"\n\t\"go.opentelemetry.io/otel/attribute\"\n\t\"go.opentelemetry.io/otel/codes\"\n)\n\n// Transport for tracing Elastic operations.\ntype Transport struct {\n\trt http.RoundTripper\n}\n\n// Option signature for specifying options, e.g. WithRoundTripper.\ntype Option func(t *Transport)\n\n// WithRoundTripper specifies the http.RoundTripper to call\n// next after this transport. If it is nil (default), the\n// transport will use http.DefaultTransport.\nfunc WithRoundTripper(rt http.RoundTripper) Option {\n\treturn func(t *Transport) {\n\t\tt.rt = rt\n\t}\n}\n\n// NewTransport specifies a transport that will trace Elastic\n// and report back via OpenTracing.\nfunc NewTransport(opts ...Option) *Transport {\n\tt := &Transport{}\n\tfor _, o := range opts {\n\t\to(t)\n\t}\n\treturn t\n}\n\n// RoundTrip captures the request and starts an OpenTracing span\n// for Elastic PerformRequest operation.\nfunc (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {\n\tctx, span := otel.Tracer(\"Elastic\").Start(req.Context(), \"PerformRequest\")\n\tdefer span.End()\n\n\treq = req.WithContext(ctx)\n\n\t// See General (https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/span-general.md)\n\t// and HTTP (https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md)\n\tspan.SetAttributes(\n\t\tattribute.String(\"code.namespace\", \"github.com/olivere/elastic/v7\"),\n\t\tattribute.String(\"code.function\", \"PerformRequest\"),\n\t\tattribute.String(\"http.url\", req.URL.Redacted()),\n\t\tattribute.String(\"http.method\", req.Method),\n\t\tattribute.String(\"http.scheme\", req.URL.Scheme),\n\t\tattribute.String(\"http.host\", req.URL.Hostname()),\n\t\tattribute.String(\"http.path\", req.URL.Path),\n\t\tattribute.String(\"http.user_agent\", req.UserAgent()),\n\t)\n\n\tvar (\n\t\tresp *http.Response\n\t\terr  error\n\t)\n\tif t.rt != nil {\n\t\tresp, err = t.rt.RoundTrip(req)\n\t} else {\n\t\tresp, err = http.DefaultTransport.RoundTrip(req)\n\t}\n\tif err != nil {\n\t\tspan.RecordError(err)\n\t\tspan.SetStatus(codes.Error, err.Error())\n\t}\n\tif resp != nil {\n\t\tspan.SetAttributes(attribute.Int64(\"http.status_code\", int64(resp.StatusCode)))\n\t}\n\n\treturn resp, err\n}\n"
  },
  {
    "path": "trace/opentelemetry/util.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage opentelemetry\n\nimport (\n\t\"strconv\"\n)\n\nfunc atouint16(s string) uint16 {\n\tv, _ := strconv.ParseUint(s, 10, 16)\n\treturn uint16(v)\n}\n"
  },
  {
    "path": "trace/opentracing/transport.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage opentracing\n\nimport (\n\t\"net/http\"\n\n\t\"github.com/opentracing/opentracing-go\"\n\t\"github.com/opentracing/opentracing-go/ext\"\n)\n\n// Transport for tracing Elastic operations.\ntype Transport struct {\n\trt http.RoundTripper\n}\n\n// Option signature for specifying options, e.g. WithRoundTripper.\ntype Option func(t *Transport)\n\n// WithRoundTripper specifies the http.RoundTripper to call\n// next after this transport. If it is nil (default), the\n// transport will use http.DefaultTransport.\nfunc WithRoundTripper(rt http.RoundTripper) Option {\n\treturn func(t *Transport) {\n\t\tt.rt = rt\n\t}\n}\n\n// NewTransport specifies a transport that will trace Elastic\n// and report back via OpenTracing.\nfunc NewTransport(opts ...Option) *Transport {\n\tt := &Transport{}\n\tfor _, o := range opts {\n\t\to(t)\n\t}\n\treturn t\n}\n\n// RoundTrip captures the request and starts an OpenTracing span\n// for Elastic PerformRequest operation.\nfunc (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {\n\tspan, ctx := opentracing.StartSpanFromContext(req.Context(), \"PerformRequest\")\n\treq = req.WithContext(ctx)\n\tdefer span.Finish()\n\n\text.Component.Set(span, \"github.com/olivere/elastic/v7\")\n\text.HTTPUrl.Set(span, req.URL.Redacted())\n\text.HTTPMethod.Set(span, req.Method)\n\text.PeerHostname.Set(span, req.URL.Hostname())\n\text.PeerPort.Set(span, atouint16(req.URL.Port()))\n\n\tvar (\n\t\tresp *http.Response\n\t\terr  error\n\t)\n\tif t.rt != nil {\n\t\tresp, err = t.rt.RoundTrip(req)\n\t} else {\n\t\tresp, err = http.DefaultTransport.RoundTrip(req)\n\t}\n\tif err != nil {\n\t\text.Error.Set(span, true)\n\t}\n\tif resp != nil {\n\t\text.HTTPStatusCode.Set(span, uint16(resp.StatusCode))\n\t}\n\n\treturn resp, err\n}\n"
  },
  {
    "path": "trace/opentracing/transport_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage opentracing\n\nimport (\n\t\"context\"\n\t\"net/http\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/opentracing/opentracing-go\"\n\t\"github.com/opentracing/opentracing-go/mocktracer\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc TestTransportIntegration(t *testing.T) {\n\t// Mock tracer\n\ttracer := mocktracer.New()\n\topentracing.InitGlobalTracer(tracer)\n\n\t// Setup a simple transport\n\ttr := NewTransport()\n\thttpClient := &http.Client{\n\t\tTransport: tr,\n\t}\n\n\t// Create a simple Ping request via Elastic\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(\"http://127.0.0.1:9210\"),\n\t\telastic.SetHealthcheck(false),\n\t\telastic.SetSniff(false),\n\t\telastic.SetBasicAuth(\"elastic\", \"elastic\"),\n\t\telastic.SetHttpClient(httpClient),\n\t)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_, err = client.Search(\"_all\").Query(elastic.NewMatchAllQuery()).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Check the data written into tracer\n\tspans := tracer.FinishedSpans()\n\tif want, have := 1, len(spans); want != have {\n\t\tt.Fatalf(\"want %d finished spans, have %d\", want, have)\n\t}\n\tspan := spans[0]\n\n\tif want, have := \"PerformRequest\", span.OperationName; want != have {\n\t\tt.Fatalf(\"want Span.OperationName=%q, have %q\", want, have)\n\t}\n\tif want, have := \"github.com/olivere/elastic/v7\", span.Tag(\"component\"); want != have {\n\t\tt.Fatalf(\"want component tag=%q, have %q\", want, have)\n\t}\n\thttpURL, ok := span.Tag(\"http.url\").(string)\n\tif !ok || httpURL == \"\" {\n\t\tt.Fatalf(\"want http.url tag=%q to be a non-empty string (found type %T)\", \"http.url\", span.Tag(\"http.url\"))\n\t}\n\tif want, have := \"http://127.0.0.1:9210/_all/_search\", httpURL; want != have {\n\t\tt.Fatalf(\"want http.url tag=%q, have %q\", want, have)\n\t}\n\tif strings.Contains(httpURL, \"elastic\") {\n\t\tt.Fatalf(\"want http.url tag %q to not contain username and/or password: %s\", \"URL\", span.Tag(\"http.url\"))\n\t}\n\tif want, have := \"POST\", span.Tag(\"http.method\"); want != have {\n\t\tt.Fatalf(\"want http.method tag=%q, have %q\", want, have)\n\t}\n\tif want, have := uint16(http.StatusOK), span.Tag(\"http.status_code\"); want != have {\n\t\tt.Fatalf(\"want http.status_code tag=%v (%T), have %v (%T)\", want, want, have, have)\n\t}\n}\n"
  },
  {
    "path": "trace/opentracing/transport_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage opentracing\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/opentracing/opentracing-go\"\n\t\"github.com/opentracing/opentracing-go/mocktracer\"\n\n\t\"github.com/olivere/elastic/v7\"\n)\n\nfunc TestTransport(t *testing.T) {\n\tts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\tusername, password, ok := r.BasicAuth()\n\t\tif !ok || username != \"alice\" || password != \"secret\" {\n\t\t\tw.WriteHeader(http.StatusForbidden)\n\t\t\treturn\n\t\t}\n\n\t\tswitch r.URL.Path {\n\t\tcase \"/\":\n\t\t\tw.WriteHeader(http.StatusOK)\n\t\t\tfmt.Fprintln(w, `{\n\t\t\t\t\"name\" : \"Qg28M36\",\n\t\t\t\t\"cluster_name\" : \"docker-cluster\",\n\t\t\t\t\"cluster_uuid\" : \"rwHa7BBnRC2h8KoDfCbmuQ\",\n\t\t\t\t\"version\" : {\n\t\t\t\t\t\"number\" : \"6.3.2\",\n\t\t\t\t\t\"build_flavor\" : \"oss\",\n\t\t\t\t\t\"build_type\" : \"tar\",\n\t\t\t\t\t\"build_hash\" : \"053779d\",\n\t\t\t\t\t\"build_date\" : \"2018-07-20T05:20:23.451332Z\",\n\t\t\t\t\t\"build_snapshot\" : false,\n\t\t\t\t\t\"lucene_version\" : \"7.3.1\",\n\t\t\t\t\t\"minimum_wire_compatibility_version\" : \"5.6.0\",\n\t\t\t\t\t\"minimum_index_compatibility_version\" : \"5.0.0\"\n\t\t\t\t},\n\t\t\t\t\"tagline\" : \"You Know, for Search\"\n\t\t\t}`)\n\t\t\treturn\n\t\tdefault:\n\t\t\tw.WriteHeader(http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\t}))\n\tdefer ts.Close()\n\n\t// Mock tracer\n\ttracer := mocktracer.New()\n\topentracing.InitGlobalTracer(tracer)\n\n\t// Setup a simple transport\n\ttr := NewTransport()\n\thttpClient := &http.Client{\n\t\tTransport: tr,\n\t}\n\n\t// Create a simple Ping request via Elastic\n\tclient, err := elastic.NewClient(\n\t\telastic.SetURL(ts.URL),\n\t\telastic.SetHttpClient(httpClient),\n\t\telastic.SetHealthcheck(false),\n\t\telastic.SetSniff(false),\n\t\telastic.SetBasicAuth(\"alice\", \"secret\"),\n\t)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, code, err := client.Ping(ts.URL).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := http.StatusOK, code; want != have {\n\t\tt.Fatalf(\"want Status=%d, have %d\", want, have)\n\t}\n\tif want, have := \"You Know, for Search\", res.TagLine; want != have {\n\t\tt.Fatalf(\"want TagLine=%q, have %q\", want, have)\n\t}\n\n\t// Check the data written into tracer\n\tspans := tracer.FinishedSpans()\n\tif want, have := 1, len(spans); want != have {\n\t\tt.Fatalf(\"want %d finished spans, have %d\", want, have)\n\t}\n\tspan := spans[0]\n\n\tif want, have := \"PerformRequest\", span.OperationName; want != have {\n\t\tt.Fatalf(\"want Span.OperationName=%q, have %q\", want, have)\n\t}\n\tif want, have := \"github.com/olivere/elastic/v7\", span.Tag(\"component\"); want != have {\n\t\tt.Fatalf(\"want component tag=%q, have %q\", want, have)\n\t}\n\thttpURL, ok := span.Tag(\"http.url\").(string)\n\tif !ok || httpURL == \"\" {\n\t\tt.Fatalf(\"want http.url tag=%q to be a non-empty string (found type %T)\", \"http.url\", span.Tag(\"http.url\"))\n\t}\n\tif want, have := ts.URL+\"/\", httpURL; want != have {\n\t\tt.Fatalf(\"want http.url tag=%q, have %q\", want, have)\n\t}\n\tt.Logf(\"http.url = %q\", httpURL)\n\tif strings.Contains(httpURL, \"alice\") || strings.Contains(httpURL, \"password\") {\n\t\tt.Fatalf(\"want http.url tag %q to not contain username and/or password: %s\", \"URL\", span.Tag(\"http.url\"))\n\t}\n\tif want, have := \"GET\", span.Tag(\"http.method\"); want != have {\n\t\tt.Fatalf(\"want http.method tag=%q, have %q\", want, have)\n\t}\n\tif want, have := uint16(http.StatusOK), span.Tag(\"http.status_code\"); want != have {\n\t\tt.Fatalf(\"want http.status_code tag=%v (%T), have %v (%T)\", want, want, have, have)\n\t}\n}\n"
  },
  {
    "path": "trace/opentracing/util.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage opentracing\n\nimport (\n\t\"strconv\"\n)\n\nfunc atouint16(s string) uint16 {\n\tv, _ := strconv.ParseUint(s, 10, 16)\n\treturn uint16(v)\n}\n"
  },
  {
    "path": "update.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// UpdateService updates a document in Elasticsearch.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-update.html\n// for details.\ntype UpdateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex               string\n\ttyp                 string\n\tid                  string\n\trouting             string\n\tparent              string\n\tscript              *Script\n\tfields              []string\n\tfsc                 *FetchSourceContext\n\tversion             *int64\n\tversionType         string\n\tretryOnConflict     *int\n\trefresh             string\n\twaitForActiveShards string\n\tupsert              interface{}\n\tscriptedUpsert      *bool\n\tdocAsUpsert         *bool\n\tdetectNoop          *bool\n\tdoc                 interface{}\n\ttimeout             string\n\tifSeqNo             *int64\n\tifPrimaryTerm       *int64\n}\n\n// NewUpdateService creates the service to update documents in Elasticsearch.\nfunc NewUpdateService(client *Client) *UpdateService {\n\treturn &UpdateService{\n\t\tclient: client,\n\t\ttyp:    \"_doc\",\n\t\tfields: make([]string, 0),\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *UpdateService) Pretty(pretty bool) *UpdateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *UpdateService) Human(human bool) *UpdateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *UpdateService) ErrorTrace(errorTrace bool) *UpdateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *UpdateService) FilterPath(filterPath ...string) *UpdateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *UpdateService) Header(name string, value string) *UpdateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *UpdateService) Headers(headers http.Header) *UpdateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is the name of the Elasticsearch index (required).\nfunc (s *UpdateService) Index(name string) *UpdateService {\n\ts.index = name\n\treturn s\n}\n\n// Type is the type of the document.\n//\n// Deprecated: Types are in the process of being removed.\nfunc (s *UpdateService) Type(typ string) *UpdateService {\n\ts.typ = typ\n\treturn s\n}\n\n// Id is the identifier of the document to update (required).\nfunc (s *UpdateService) Id(id string) *UpdateService {\n\ts.id = id\n\treturn s\n}\n\n// Routing specifies a specific routing value.\nfunc (s *UpdateService) Routing(routing string) *UpdateService {\n\ts.routing = routing\n\treturn s\n}\n\n// Parent sets the id of the parent document.\nfunc (s *UpdateService) Parent(parent string) *UpdateService {\n\ts.parent = parent\n\treturn s\n}\n\n// Script is the script definition.\nfunc (s *UpdateService) Script(script *Script) *UpdateService {\n\ts.script = script\n\treturn s\n}\n\n// RetryOnConflict specifies how many times the operation should be retried\n// when a conflict occurs (default: 0).\nfunc (s *UpdateService) RetryOnConflict(retryOnConflict int) *UpdateService {\n\ts.retryOnConflict = &retryOnConflict\n\treturn s\n}\n\n// Fields is a list of fields to return in the response.\nfunc (s *UpdateService) Fields(fields ...string) *UpdateService {\n\ts.fields = make([]string, 0, len(fields))\n\ts.fields = append(s.fields, fields...)\n\treturn s\n}\n\n// Version defines the explicit version number for concurrency control.\nfunc (s *UpdateService) Version(version int64) *UpdateService {\n\ts.version = &version\n\treturn s\n}\n\n// VersionType is e.g. \"internal\".\nfunc (s *UpdateService) VersionType(versionType string) *UpdateService {\n\ts.versionType = versionType\n\treturn s\n}\n\n// Refresh the index after performing the update.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *UpdateService) Refresh(refresh string) *UpdateService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// WaitForActiveShards sets the number of shard copies that must be active before\n// proceeding with the update operation. Defaults to 1, meaning the primary shard only.\n// Set to `all` for all shard copies, otherwise set to any non-negative value less than\n// or equal to the total number of copies for the shard (number of replicas + 1).\nfunc (s *UpdateService) WaitForActiveShards(waitForActiveShards string) *UpdateService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// Doc allows for updating a partial document.\nfunc (s *UpdateService) Doc(doc interface{}) *UpdateService {\n\ts.doc = doc\n\treturn s\n}\n\n// Upsert can be used to index the document when it doesn't exist yet.\n// Use this e.g. to initialize a document with a default value.\nfunc (s *UpdateService) Upsert(doc interface{}) *UpdateService {\n\ts.upsert = doc\n\treturn s\n}\n\n// DocAsUpsert can be used to insert the document if it doesn't already exist.\nfunc (s *UpdateService) DocAsUpsert(docAsUpsert bool) *UpdateService {\n\ts.docAsUpsert = &docAsUpsert\n\treturn s\n}\n\n// DetectNoop will instruct Elasticsearch to check if changes will occur\n// when updating via Doc. It there aren't any changes, the request will\n// turn into a no-op.\nfunc (s *UpdateService) DetectNoop(detectNoop bool) *UpdateService {\n\ts.detectNoop = &detectNoop\n\treturn s\n}\n\n// ScriptedUpsert should be set to true if the referenced script\n// (defined in Script or ScriptId) should be called to perform an insert.\n// The default is false.\nfunc (s *UpdateService) ScriptedUpsert(scriptedUpsert bool) *UpdateService {\n\ts.scriptedUpsert = &scriptedUpsert\n\treturn s\n}\n\n// Timeout is an explicit timeout for the operation, e.g. \"1000\", \"1s\" or \"500ms\".\nfunc (s *UpdateService) Timeout(timeout string) *UpdateService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// IfSeqNo indicates to only perform the update operation if the last\n// operation that has changed the document has the specified sequence number.\nfunc (s *UpdateService) IfSeqNo(seqNo int64) *UpdateService {\n\ts.ifSeqNo = &seqNo\n\treturn s\n}\n\n// IfPrimaryTerm indicates to only perform the update operation if the\n// last operation that has changed the document has the specified primary term.\nfunc (s *UpdateService) IfPrimaryTerm(primaryTerm int64) *UpdateService {\n\ts.ifPrimaryTerm = &primaryTerm\n\treturn s\n}\n\n// FetchSource asks Elasticsearch to return the updated _source in the response.\nfunc (s *UpdateService) FetchSource(fetchSource bool) *UpdateService {\n\tif s.fsc == nil {\n\t\ts.fsc = NewFetchSourceContext(fetchSource)\n\t} else {\n\t\ts.fsc.SetFetchSource(fetchSource)\n\t}\n\treturn s\n}\n\n// FetchSourceContext indicates that _source should be returned in the response,\n// allowing wildcard patterns to be defined via FetchSourceContext.\nfunc (s *UpdateService) FetchSourceContext(fetchSourceContext *FetchSourceContext) *UpdateService {\n\ts.fsc = fetchSourceContext\n\treturn s\n}\n\n// url returns the URL part of the document request.\nfunc (s *UpdateService) url() (string, url.Values, error) {\n\t// Build url\n\tvar path string\n\tvar err error\n\tif s.typ == \"\" || s.typ == \"_doc\" {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_update/{id}\", map[string]string{\n\t\t\t\"index\": s.index,\n\t\t\t\"id\":    s.id,\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/{id}/_update\", map[string]string{\n\t\t\t\"index\": s.index,\n\t\t\t\"type\":  s.typ,\n\t\t\t\"id\":    s.id,\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.parent != \"\" {\n\t\tparams.Set(\"parent\", s.parent)\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Set(\"refresh\", s.refresh)\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\tif len(s.fields) > 0 {\n\t\tparams.Set(\"fields\", strings.Join(s.fields, \",\"))\n\t}\n\tif s.version != nil {\n\t\tparams.Set(\"version\", fmt.Sprintf(\"%d\", *s.version))\n\t}\n\tif s.versionType != \"\" {\n\t\tparams.Set(\"version_type\", s.versionType)\n\t}\n\tif s.retryOnConflict != nil {\n\t\tparams.Set(\"retry_on_conflict\", fmt.Sprintf(\"%v\", *s.retryOnConflict))\n\t}\n\tif v := s.ifSeqNo; v != nil {\n\t\tparams.Set(\"if_seq_no\", fmt.Sprintf(\"%d\", *v))\n\t}\n\tif v := s.ifPrimaryTerm; v != nil {\n\t\tparams.Set(\"if_primary_term\", fmt.Sprintf(\"%d\", *v))\n\t}\n\treturn path, params, nil\n}\n\n// body returns the body part of the document request.\nfunc (s *UpdateService) body() (interface{}, error) {\n\tsource := make(map[string]interface{})\n\n\tif s.script != nil {\n\t\tsrc, err := s.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"script\"] = src\n\t}\n\n\tif v := s.scriptedUpsert; v != nil {\n\t\tsource[\"scripted_upsert\"] = *v\n\t}\n\n\tif s.upsert != nil {\n\t\tsource[\"upsert\"] = s.upsert\n\t}\n\n\tif s.doc != nil {\n\t\tsource[\"doc\"] = s.doc\n\t}\n\tif v := s.docAsUpsert; v != nil {\n\t\tsource[\"doc_as_upsert\"] = *v\n\t}\n\tif v := s.detectNoop; v != nil {\n\t\tsource[\"detect_noop\"] = *v\n\t}\n\tif s.fsc != nil {\n\t\tsrc, err := s.fsc.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"_source\"] = src\n\t}\n\n\treturn source, nil\n}\n\n// Do executes the update operation.\nfunc (s *UpdateService) Do(ctx context.Context) (*UpdateResponse, error) {\n\tpath, params, err := s.url()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get body of the request\n\tbody, err := s.body()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return result\n\tret := new(UpdateResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// UpdateResponse is the result of updating a document in Elasticsearch.\ntype UpdateResponse struct {\n\tIndex         string      `json:\"_index,omitempty\"`\n\tType          string      `json:\"_type,omitempty\"`\n\tId            string      `json:\"_id,omitempty\"`\n\tVersion       int64       `json:\"_version,omitempty\"`\n\tResult        string      `json:\"result,omitempty\"`\n\tShards        *ShardsInfo `json:\"_shards,omitempty\"`\n\tSeqNo         int64       `json:\"_seq_no,omitempty\"`\n\tPrimaryTerm   int64       `json:\"_primary_term,omitempty\"`\n\tStatus        int         `json:\"status,omitempty\"`\n\tForcedRefresh bool        `json:\"forced_refresh,omitempty\"`\n\tGetResult     *GetResult  `json:\"get,omitempty\"`\n}\n"
  },
  {
    "path": "update_by_query.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// UpdateByQueryService is documented at https://www.elastic.co/guide/en/elasticsearch/plugins/master/plugins-reindex.html.\ntype UpdateByQueryService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex                  []string\n\ttyp                    []string\n\tscript                 *Script\n\tquery                  Query\n\tbody                   interface{}\n\txSource                []string\n\txSourceExclude         []string\n\txSourceInclude         []string\n\tallowNoIndices         *bool\n\tanalyzeWildcard        *bool\n\tanalyzer               string\n\tconflicts              string\n\tdefaultOperator        string\n\tdocvalueFields         []string\n\tdf                     string\n\texpandWildcards        string\n\texplain                *bool\n\tfielddataFields        []string\n\tfrom                   *int\n\tignoreUnavailable      *bool\n\tlenient                *bool\n\tlowercaseExpandedTerms *bool\n\tmaxDocs                *int\n\tpipeline               string\n\tpreference             string\n\tq                      string\n\trefresh                string\n\trequestCache           *bool\n\trequestsPerSecond      *int\n\trouting                []string\n\tscroll                 string\n\tscrollSize             *int\n\tsearchTimeout          string\n\tsearchType             string\n\tsize                   *int\n\tslices                 interface{}\n\tsort                   []string\n\tstats                  []string\n\tstoredFields           []string\n\tsuggestField           string\n\tsuggestMode            string\n\tsuggestSize            *int\n\tsuggestText            string\n\tterminateAfter         *int\n\ttimeout                string\n\ttrackScores            *bool\n\tversion                *bool\n\tversionType            *bool\n\twaitForActiveShards    string\n\twaitForCompletion      *bool\n}\n\n// NewUpdateByQueryService creates a new UpdateByQueryService.\nfunc NewUpdateByQueryService(client *Client) *UpdateByQueryService {\n\treturn &UpdateByQueryService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *UpdateByQueryService) Pretty(pretty bool) *UpdateByQueryService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *UpdateByQueryService) Human(human bool) *UpdateByQueryService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *UpdateByQueryService) ErrorTrace(errorTrace bool) *UpdateByQueryService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *UpdateByQueryService) FilterPath(filterPath ...string) *UpdateByQueryService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *UpdateByQueryService) Header(name string, value string) *UpdateByQueryService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *UpdateByQueryService) Headers(headers http.Header) *UpdateByQueryService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index is a list of index names to search; use `_all` or empty string to\n// perform the operation on all indices.\nfunc (s *UpdateByQueryService) Index(index ...string) *UpdateByQueryService {\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// Type is a list of document types to search; leave empty to perform\n// the operation on all types.\nfunc (s *UpdateByQueryService) Type(typ ...string) *UpdateByQueryService {\n\ts.typ = append(s.typ, typ...)\n\treturn s\n}\n\n// Script sets an update script.\nfunc (s *UpdateByQueryService) Script(script *Script) *UpdateByQueryService {\n\ts.script = script\n\treturn s\n}\n\n// Body specifies the body of the request. It overrides data being specified via\n// SearchService or Script.\nfunc (s *UpdateByQueryService) Body(body string) *UpdateByQueryService {\n\ts.body = body\n\treturn s\n}\n\n// XSource is true or false to return the _source field or not,\n// or a list of fields to return.\nfunc (s *UpdateByQueryService) XSource(xSource ...string) *UpdateByQueryService {\n\ts.xSource = append(s.xSource, xSource...)\n\treturn s\n}\n\n// XSourceExclude represents a list of fields to exclude from the returned _source field.\nfunc (s *UpdateByQueryService) XSourceExclude(xSourceExclude ...string) *UpdateByQueryService {\n\ts.xSourceExclude = append(s.xSourceExclude, xSourceExclude...)\n\treturn s\n}\n\n// XSourceInclude represents a list of fields to extract and return from the _source field.\nfunc (s *UpdateByQueryService) XSourceInclude(xSourceInclude ...string) *UpdateByQueryService {\n\ts.xSourceInclude = append(s.xSourceInclude, xSourceInclude...)\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices expression\n// resolves into no concrete indices. (This includes `_all` string or when\n// no indices have been specified).\nfunc (s *UpdateByQueryService) AllowNoIndices(allowNoIndices bool) *UpdateByQueryService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// AnalyzeWildcard specifies whether wildcard and prefix queries should be\n// analyzed (default: false).\nfunc (s *UpdateByQueryService) AnalyzeWildcard(analyzeWildcard bool) *UpdateByQueryService {\n\ts.analyzeWildcard = &analyzeWildcard\n\treturn s\n}\n\n// Analyzer specifies the analyzer to use for the query string.\nfunc (s *UpdateByQueryService) Analyzer(analyzer string) *UpdateByQueryService {\n\ts.analyzer = analyzer\n\treturn s\n}\n\n// Conflicts indicates what to do when the process detects version conflicts.\n// Possible values are \"proceed\" and \"abort\".\nfunc (s *UpdateByQueryService) Conflicts(conflicts string) *UpdateByQueryService {\n\ts.conflicts = conflicts\n\treturn s\n}\n\n// AbortOnVersionConflict aborts the request on version conflicts.\n// It is an alias to setting Conflicts(\"abort\").\nfunc (s *UpdateByQueryService) AbortOnVersionConflict() *UpdateByQueryService {\n\ts.conflicts = \"abort\"\n\treturn s\n}\n\n// ProceedOnVersionConflict won't abort the request on version conflicts.\n// It is an alias to setting Conflicts(\"proceed\").\nfunc (s *UpdateByQueryService) ProceedOnVersionConflict() *UpdateByQueryService {\n\ts.conflicts = \"proceed\"\n\treturn s\n}\n\n// DefaultOperator is the default operator for query string query (AND or OR).\nfunc (s *UpdateByQueryService) DefaultOperator(defaultOperator string) *UpdateByQueryService {\n\ts.defaultOperator = defaultOperator\n\treturn s\n}\n\n// DF specifies the field to use as default where no field prefix is given in the query string.\nfunc (s *UpdateByQueryService) DF(df string) *UpdateByQueryService {\n\ts.df = df\n\treturn s\n}\n\n// DocvalueFields specifies the list of fields to return as the docvalue representation of a field for each hit.\nfunc (s *UpdateByQueryService) DocvalueFields(docvalueFields ...string) *UpdateByQueryService {\n\ts.docvalueFields = docvalueFields\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *UpdateByQueryService) ExpandWildcards(expandWildcards string) *UpdateByQueryService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// Explain specifies whether to return detailed information about score\n// computation as part of a hit.\nfunc (s *UpdateByQueryService) Explain(explain bool) *UpdateByQueryService {\n\ts.explain = &explain\n\treturn s\n}\n\n// FielddataFields is a list of fields to return as the field data\n// representation of a field for each hit.\nfunc (s *UpdateByQueryService) FielddataFields(fielddataFields ...string) *UpdateByQueryService {\n\ts.fielddataFields = append(s.fielddataFields, fielddataFields...)\n\treturn s\n}\n\n// From is the starting offset (default: 0).\nfunc (s *UpdateByQueryService) From(from int) *UpdateByQueryService {\n\ts.from = &from\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether specified concrete indices should be\n// ignored when unavailable (missing or closed).\nfunc (s *UpdateByQueryService) IgnoreUnavailable(ignoreUnavailable bool) *UpdateByQueryService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// Lenient specifies whether format-based query failures\n// (such as providing text to a numeric field) should be ignored.\nfunc (s *UpdateByQueryService) Lenient(lenient bool) *UpdateByQueryService {\n\ts.lenient = &lenient\n\treturn s\n}\n\n// LowercaseExpandedTerms specifies whether query terms should be lowercased.\nfunc (s *UpdateByQueryService) LowercaseExpandedTerms(lowercaseExpandedTerms bool) *UpdateByQueryService {\n\ts.lowercaseExpandedTerms = &lowercaseExpandedTerms\n\treturn s\n}\n\n// MaxDocs specifies maximum number of documents to process\nfunc (s *UpdateByQueryService) MaxDocs(maxDocs int) *UpdateByQueryService {\n\ts.maxDocs = &maxDocs\n\treturn s\n}\n\n// Pipeline specifies the ingest pipeline to set on index requests made by this action (default: none).\nfunc (s *UpdateByQueryService) Pipeline(pipeline string) *UpdateByQueryService {\n\ts.pipeline = pipeline\n\treturn s\n}\n\n// Preference specifies the node or shard the operation should be performed on\n// (default: random).\nfunc (s *UpdateByQueryService) Preference(preference string) *UpdateByQueryService {\n\ts.preference = preference\n\treturn s\n}\n\n// Q specifies the query in the Lucene query string syntax.\nfunc (s *UpdateByQueryService) Q(q string) *UpdateByQueryService {\n\ts.q = q\n\treturn s\n}\n\n// Query sets a query definition using the Query DSL.\nfunc (s *UpdateByQueryService) Query(query Query) *UpdateByQueryService {\n\ts.query = query\n\treturn s\n}\n\n// Refresh indicates whether the effected indexes should be refreshed.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-refresh.html\n// for details.\nfunc (s *UpdateByQueryService) Refresh(refresh string) *UpdateByQueryService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// RequestCache specifies if request cache should be used for this request\n// or not, defaults to index level setting.\nfunc (s *UpdateByQueryService) RequestCache(requestCache bool) *UpdateByQueryService {\n\ts.requestCache = &requestCache\n\treturn s\n}\n\n// RequestsPerSecond sets the throttle on this request in sub-requests per second.\n// -1 means set no throttle as does \"unlimited\" which is the only non-float this accepts.\nfunc (s *UpdateByQueryService) RequestsPerSecond(requestsPerSecond int) *UpdateByQueryService {\n\ts.requestsPerSecond = &requestsPerSecond\n\treturn s\n}\n\n// Routing is a list of specific routing values.\nfunc (s *UpdateByQueryService) Routing(routing ...string) *UpdateByQueryService {\n\ts.routing = append(s.routing, routing...)\n\treturn s\n}\n\n// Scroll specifies how long a consistent view of the index should be maintained\n// for scrolled search.\nfunc (s *UpdateByQueryService) Scroll(scroll string) *UpdateByQueryService {\n\ts.scroll = scroll\n\treturn s\n}\n\n// ScrollSize is the size on the scroll request powering the update_by_query.\nfunc (s *UpdateByQueryService) ScrollSize(scrollSize int) *UpdateByQueryService {\n\ts.scrollSize = &scrollSize\n\treturn s\n}\n\n// SearchTimeout defines an explicit timeout for each search request.\n// Defaults to no timeout.\nfunc (s *UpdateByQueryService) SearchTimeout(searchTimeout string) *UpdateByQueryService {\n\ts.searchTimeout = searchTimeout\n\treturn s\n}\n\n// SearchType is the search operation type. Possible values are\n// \"query_then_fetch\" and \"dfs_query_then_fetch\".\nfunc (s *UpdateByQueryService) SearchType(searchType string) *UpdateByQueryService {\n\ts.searchType = searchType\n\treturn s\n}\n\n// Size represents the number of hits to return (default: 10).\nfunc (s *UpdateByQueryService) Size(size int) *UpdateByQueryService {\n\ts.size = &size\n\treturn s\n}\n\n// Slices represents the number of slices (default: 1).\n// It used to  be a number, but can be set to \"auto\" as of 6.7.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/docs-update-by-query.html#docs-update-by-query-slice\n// for details.\nfunc (s *UpdateByQueryService) Slices(slices interface{}) *UpdateByQueryService {\n\ts.slices = slices\n\treturn s\n}\n\n// Sort is a list of <field>:<direction> pairs.\nfunc (s *UpdateByQueryService) Sort(sort ...string) *UpdateByQueryService {\n\ts.sort = append(s.sort, sort...)\n\treturn s\n}\n\n// SortByField adds a sort order.\nfunc (s *UpdateByQueryService) SortByField(field string, ascending bool) *UpdateByQueryService {\n\tif ascending {\n\t\ts.sort = append(s.sort, fmt.Sprintf(\"%s:asc\", field))\n\t} else {\n\t\ts.sort = append(s.sort, fmt.Sprintf(\"%s:desc\", field))\n\t}\n\treturn s\n}\n\n// Stats specifies specific tag(s) of the request for logging and statistical purposes.\nfunc (s *UpdateByQueryService) Stats(stats ...string) *UpdateByQueryService {\n\ts.stats = append(s.stats, stats...)\n\treturn s\n}\n\n// StoredFields specifies the list of stored fields to return as part of a hit.\nfunc (s *UpdateByQueryService) StoredFields(storedFields ...string) *UpdateByQueryService {\n\ts.storedFields = storedFields\n\treturn s\n}\n\n// SuggestField specifies which field to use for suggestions.\nfunc (s *UpdateByQueryService) SuggestField(suggestField string) *UpdateByQueryService {\n\ts.suggestField = suggestField\n\treturn s\n}\n\n// SuggestMode specifies the suggest mode. Possible values are\n// \"missing\", \"popular\", and \"always\".\nfunc (s *UpdateByQueryService) SuggestMode(suggestMode string) *UpdateByQueryService {\n\ts.suggestMode = suggestMode\n\treturn s\n}\n\n// SuggestSize specifies how many suggestions to return in response.\nfunc (s *UpdateByQueryService) SuggestSize(suggestSize int) *UpdateByQueryService {\n\ts.suggestSize = &suggestSize\n\treturn s\n}\n\n// SuggestText specifies the source text for which the suggestions should be returned.\nfunc (s *UpdateByQueryService) SuggestText(suggestText string) *UpdateByQueryService {\n\ts.suggestText = suggestText\n\treturn s\n}\n\n// TerminateAfter indicates the maximum number of documents to collect\n// for each shard, upon reaching which the query execution will terminate early.\nfunc (s *UpdateByQueryService) TerminateAfter(terminateAfter int) *UpdateByQueryService {\n\ts.terminateAfter = &terminateAfter\n\treturn s\n}\n\n// Timeout is the time each individual bulk request should wait for shards\n// that are unavailable.\nfunc (s *UpdateByQueryService) Timeout(timeout string) *UpdateByQueryService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// TimeoutInMillis sets the timeout in milliseconds.\nfunc (s *UpdateByQueryService) TimeoutInMillis(timeoutInMillis int) *UpdateByQueryService {\n\ts.timeout = fmt.Sprintf(\"%dms\", timeoutInMillis)\n\treturn s\n}\n\n// TrackScores indicates whether to calculate and return scores even if\n// they are not used for sorting.\nfunc (s *UpdateByQueryService) TrackScores(trackScores bool) *UpdateByQueryService {\n\ts.trackScores = &trackScores\n\treturn s\n}\n\n// Version specifies whether to return document version as part of a hit.\nfunc (s *UpdateByQueryService) Version(version bool) *UpdateByQueryService {\n\ts.version = &version\n\treturn s\n}\n\n// VersionType indicates if the document increment the version number (internal)\n// on hit or not (reindex).\nfunc (s *UpdateByQueryService) VersionType(versionType bool) *UpdateByQueryService {\n\ts.versionType = &versionType\n\treturn s\n}\n\n// WaitForActiveShards sets the number of shard copies that must be active before proceeding\n// with the update by query operation. Defaults to 1, meaning the primary shard only.\n// Set to `all` for all shard copies, otherwise set to any non-negative value less than or equal\n// to the total number of copies for the shard (number of replicas + 1).\nfunc (s *UpdateByQueryService) WaitForActiveShards(waitForActiveShards string) *UpdateByQueryService {\n\ts.waitForActiveShards = waitForActiveShards\n\treturn s\n}\n\n// WaitForCompletion indicates if the request should block until the reindex is complete.\nfunc (s *UpdateByQueryService) WaitForCompletion(waitForCompletion bool) *UpdateByQueryService {\n\ts.waitForCompletion = &waitForCompletion\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *UpdateByQueryService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.typ) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/_update_by_query\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t\t\"type\":  strings.Join(s.typ, \",\"),\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_update_by_query\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif len(s.xSource) > 0 {\n\t\tparams.Set(\"_source\", strings.Join(s.xSource, \",\"))\n\t}\n\tif len(s.xSourceExclude) > 0 {\n\t\tparams.Set(\"_source_excludes\", strings.Join(s.xSourceExclude, \",\"))\n\t}\n\tif len(s.xSourceInclude) > 0 {\n\t\tparams.Set(\"_source_includes\", strings.Join(s.xSourceInclude, \",\"))\n\t}\n\tif s.allowNoIndices != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprintf(\"%v\", *s.allowNoIndices))\n\t}\n\tif s.analyzer != \"\" {\n\t\tparams.Set(\"analyzer\", s.analyzer)\n\t}\n\tif v := s.analyzeWildcard; v != nil {\n\t\tparams.Set(\"analyze_wildcard\", fmt.Sprint(*v))\n\t}\n\tif s.conflicts != \"\" {\n\t\tparams.Set(\"conflicts\", s.conflicts)\n\t}\n\tif s.defaultOperator != \"\" {\n\t\tparams.Set(\"default_operator\", s.defaultOperator)\n\t}\n\tif s.df != \"\" {\n\t\tparams.Set(\"df\", s.df)\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif v := s.explain; v != nil {\n\t\tparams.Set(\"explain\", fmt.Sprint(*v))\n\t}\n\tif len(s.storedFields) > 0 {\n\t\tparams.Set(\"stored_fields\", strings.Join(s.storedFields, \",\"))\n\t}\n\tif len(s.docvalueFields) > 0 {\n\t\tparams.Set(\"docvalue_fields\", strings.Join(s.docvalueFields, \",\"))\n\t}\n\tif len(s.fielddataFields) > 0 {\n\t\tparams.Set(\"fielddata_fields\", strings.Join(s.fielddataFields, \",\"))\n\t}\n\tif s.from != nil {\n\t\tparams.Set(\"from\", fmt.Sprintf(\"%d\", *s.from))\n\t}\n\tif v := s.ignoreUnavailable; v != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*v))\n\t}\n\tif v := s.lenient; v != nil {\n\t\tparams.Set(\"lenient\", fmt.Sprint(*v))\n\t}\n\tif v := s.lowercaseExpandedTerms; v != nil {\n\t\tparams.Set(\"lowercase_expanded_terms\", fmt.Sprint(*v))\n\t}\n\tif s.maxDocs != nil {\n\t\tparams.Set(\"max_docs\", fmt.Sprintf(\"%d\", *s.maxDocs))\n\t}\n\tif s.pipeline != \"\" {\n\t\tparams.Set(\"pipeline\", s.pipeline)\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif s.q != \"\" {\n\t\tparams.Set(\"q\", s.q)\n\t}\n\tif s.refresh != \"\" {\n\t\tparams.Set(\"refresh\", s.refresh)\n\t}\n\tif v := s.requestCache; v != nil {\n\t\tparams.Set(\"request_cache\", fmt.Sprint(*v))\n\t}\n\tif len(s.routing) > 0 {\n\t\tparams.Set(\"routing\", strings.Join(s.routing, \",\"))\n\t}\n\tif s.scroll != \"\" {\n\t\tparams.Set(\"scroll\", s.scroll)\n\t}\n\tif s.scrollSize != nil {\n\t\tparams.Set(\"scroll_size\", fmt.Sprintf(\"%d\", *s.scrollSize))\n\t}\n\tif s.searchTimeout != \"\" {\n\t\tparams.Set(\"search_timeout\", s.searchTimeout)\n\t}\n\tif s.searchType != \"\" {\n\t\tparams.Set(\"search_type\", s.searchType)\n\t}\n\tif s.size != nil {\n\t\tparams.Set(\"size\", fmt.Sprintf(\"%d\", *s.size))\n\t}\n\tif s.slices != nil {\n\t\tparams.Set(\"slices\", fmt.Sprintf(\"%v\", s.slices))\n\t}\n\tif len(s.sort) > 0 {\n\t\tparams.Set(\"sort\", strings.Join(s.sort, \",\"))\n\t}\n\tif len(s.stats) > 0 {\n\t\tparams.Set(\"stats\", strings.Join(s.stats, \",\"))\n\t}\n\tif s.suggestField != \"\" {\n\t\tparams.Set(\"suggest_field\", s.suggestField)\n\t}\n\tif s.suggestMode != \"\" {\n\t\tparams.Set(\"suggest_mode\", s.suggestMode)\n\t}\n\tif s.suggestSize != nil {\n\t\tparams.Set(\"suggest_size\", fmt.Sprintf(\"%v\", *s.suggestSize))\n\t}\n\tif s.suggestText != \"\" {\n\t\tparams.Set(\"suggest_text\", s.suggestText)\n\t}\n\tif s.terminateAfter != nil {\n\t\tparams.Set(\"terminate_after\", fmt.Sprintf(\"%v\", *s.terminateAfter))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif v := s.trackScores; v != nil {\n\t\tparams.Set(\"track_scores\", fmt.Sprint(*v))\n\t}\n\tif v := s.version; v != nil {\n\t\tparams.Set(\"version\", fmt.Sprint(*v))\n\t}\n\tif v := s.versionType; v != nil {\n\t\tparams.Set(\"version_type\", fmt.Sprint(*v))\n\t}\n\tif s.waitForActiveShards != \"\" {\n\t\tparams.Set(\"wait_for_active_shards\", s.waitForActiveShards)\n\t}\n\tif v := s.waitForCompletion; v != nil {\n\t\tparams.Set(\"wait_for_completion\", fmt.Sprint(*v))\n\t}\n\tif s.requestsPerSecond != nil {\n\t\tparams.Set(\"requests_per_second\", fmt.Sprintf(\"%v\", *s.requestsPerSecond))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *UpdateByQueryService) Validate() error {\n\tvar invalid []string\n\tif len(s.index) == 0 {\n\t\tinvalid = append(invalid, \"Index\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// getBody returns the body part of the document request.\nfunc (s *UpdateByQueryService) getBody() (interface{}, error) {\n\tif s.body != nil {\n\t\treturn s.body, nil\n\t}\n\tsource := make(map[string]interface{})\n\tif s.script != nil {\n\t\tsrc, err := s.script.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"script\"] = src\n\t}\n\tif s.query != nil {\n\t\tsrc, err := s.query.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tsource[\"query\"] = src\n\t}\n\treturn source, nil\n}\n\n// Do executes the operation.\nfunc (s *UpdateByQueryService) Do(ctx context.Context) (*BulkIndexByScrollResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tbody, err := s.getBody()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:       \"POST\",\n\t\tPath:         path,\n\t\tParams:       params,\n\t\tBody:         body,\n\t\tHeaders:      s.headers,\n\t\tIgnoreErrors: []int{http.StatusConflict},\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response (BulkIndexByScrollResponse is defined in DeleteByQuery)\n\tret := new(BulkIndexByScrollResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// DoAsync executes the update-by-query operation asynchronously by starting a new task.\n// Callers need to use the Task Management API to watch the outcome of the reindexing\n// operation.\nfunc (s *UpdateByQueryService) DoAsync(ctx context.Context) (*StartTaskResult, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// DoAsync only makes sense with WaitForCompletion set to true\n\tif s.waitForCompletion != nil && *s.waitForCompletion {\n\t\treturn nil, fmt.Errorf(\"cannot start a task with WaitForCompletion set to true\")\n\t}\n\tf := false\n\ts.waitForCompletion = &f\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tbody, err := s.getBody()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:       \"POST\",\n\t\tPath:         path,\n\t\tParams:       params,\n\t\tBody:         body,\n\t\tHeaders:      s.headers,\n\t\tIgnoreErrors: []int{http.StatusConflict},\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(StartTaskResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n"
  },
  {
    "path": "update_by_query_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestUpdateByQueryBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tIndices   []string\n\t\tTypes     []string\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{},\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{},\n\t\t\t\"/index1/_update_by_query\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{},\n\t\t\t\"/index1%2Cindex2/_update_by_query\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{},\n\t\t\t[]string{\"type1\"},\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\"},\n\t\t\t[]string{\"type1\"},\n\t\t\t\"/index1/type1/_update_by_query\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t[]string{\"index1\", \"index2\"},\n\t\t\t[]string{\"type1\", \"type2\"},\n\t\t\t\"/index1%2Cindex2/type1%2Ctype2/_update_by_query\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.UpdateByQuery().Index(test.Indices...).Type(test.Types...)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestUpdateByQueryBodyWithQuery(t *testing.T) {\n\tclient := setupTestClient(t)\n\tout, err := client.UpdateByQuery().Query(NewTermQuery(\"user\", \"olivere\")).getBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"query\":{\"term\":{\"user\":\"olivere\"}}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestUpdateByQueryBodyWithQueryAndScript(t *testing.T) {\n\tclient := setupTestClient(t)\n\tout, err := client.UpdateByQuery().\n\t\tQuery(NewTermQuery(\"user\", \"olivere\")).\n\t\tScript(NewScriptInline(\"ctx._source.likes++\")).\n\t\tgetBody()\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tb, err := json.Marshal(out)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tgot := string(b)\n\twant := `{\"query\":{\"term\":{\"user\":\"olivere\"}},\"script\":{\"source\":\"ctx._source.likes++\"}}`\n\tif got != want {\n\t\tt.Fatalf(\"\\ngot  %s\\nwant %s\", got, want)\n\t}\n}\n\nfunc TestUpdateByQuery(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tesversion, err := client.ElasticsearchVersion(DefaultURL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif esversion < \"2.3.0\" {\n\t\tt.Skipf(\"Elasticsearch %v does not support update-by-query yet\", esversion)\n\t}\n\n\tsourceCount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif sourceCount <= 0 {\n\t\tt.Fatalf(\"expected more than %d documents; got: %d\", 0, sourceCount)\n\t}\n\n\tres, err := client.UpdateByQuery(testIndexName).ProceedOnVersionConflict().Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"response is nil\")\n\t}\n\tif res.Updated != sourceCount {\n\t\tt.Fatalf(\"expected %d; got: %d\", sourceCount, res.Updated)\n\t}\n}\n\nfunc TestUpdateByQueryAsync(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\tesversion, err := client.ElasticsearchVersion(DefaultURL)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif esversion < \"2.3.0\" {\n\t\tt.Skipf(\"Elasticsearch %v does not support update-by-query yet\", esversion)\n\t}\n\n\tsourceCount, err := client.Count(testIndexName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif sourceCount <= 0 {\n\t\tt.Fatalf(\"expected more than %d documents; got: %d\", 0, sourceCount)\n\t}\n\n\tres, err := client.UpdateByQuery(testIndexName).\n\t\tProceedOnVersionConflict().\n\t\tSlices(\"auto\").\n\t\tDoAsync(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected result != nil\")\n\t}\n\tif res.TaskId == \"\" {\n\t\tt.Errorf(\"expected a task id, got %+v\", res)\n\t}\n\n\ttasksGetTask := client.TasksGetTask()\n\ttaskStatus, err := tasksGetTask.TaskId(res.TaskId).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif taskStatus == nil {\n\t\tt.Fatal(\"expected task status result != nil\")\n\t}\n}\n\nfunc TestUpdateByQueryConflict(t *testing.T) {\n\tfail := func(r *http.Request) (*http.Response, error) {\n\t\tbody := `{\n\t\t\t\"took\": 3,\n\t\t\t\"timed_out\": false,\n\t\t\t\"total\": 1,\n\t\t\t\"updated\": 0,\n\t\t\t\"deleted\": 0,\n\t\t\t\"batches\": 1,\n\t\t\t\"version_conflicts\": 1,\n\t\t\t\"noops\": 0,\n\t\t\t\"retries\": {\n\t\t\t  \"bulk\": 0,\n\t\t\t  \"search\": 0\n\t\t\t},\n\t\t\t\"throttled_millis\": 0,\n\t\t\t\"requests_per_second\": -1,\n\t\t\t\"throttled_until_millis\": 0,\n\t\t\t\"failures\": [\n\t\t\t  {\n\t\t\t\t\"index\": \"a\",\n\t\t\t\t\"type\": \"_doc\",\n\t\t\t\t\"id\": \"yjsmdGsBm363wfQmSbhj\",\n\t\t\t\t\"cause\": {\n\t\t\t\t  \"type\": \"version_conflict_engine_exception\",\n\t\t\t\t  \"reason\": \"[_doc][yjsmdGsBm363wfQmSbhj]: version conflict, current version [4] is different than the one provided [3]\",\n\t\t\t\t  \"index_uuid\": \"1rmL3mt8TimwshF-M1DxdQ\",\n\t\t\t\t  \"shard\": \"0\",\n\t\t\t\t  \"index\": \"a\"\n\t\t\t\t},\n\t\t\t\t\"status\": 409\n\t\t\t  }\n\t\t\t]\n\t\t   }`\n\t\treturn &http.Response{\n\t\t\tStatusCode:    http.StatusConflict,\n\t\t\tBody:          ioutil.NopCloser(strings.NewReader(body)),\n\t\t\tContentLength: int64(len(body)),\n\t\t}, nil\n\t}\n\n\t// Run against a failing endpoint and see if PerformRequest\n\t// retries correctly.\n\ttr := &failingTransport{path: \"/example/_update_by_query\", fail: fail}\n\thttpClient := &http.Client{Transport: tr}\n\tclient, err := NewClient(SetHttpClient(httpClient), SetHealthcheck(false))\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tres, err := client.UpdateByQuery(\"example\").ProceedOnVersionConflict().Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"mock should not be failed %+v\", err)\n\t}\n\tif res.Took != 3 {\n\t\tt.Errorf(\"took should be 3, got %d\", res.Took)\n\t}\n\tif res.Total != 1 {\n\t\tt.Errorf(\"total should be 1, got %d\", res.Total)\n\t}\n\tif res.VersionConflicts != 1 {\n\t\tt.Errorf(\"total should be 1, got %d\", res.VersionConflicts)\n\t}\n\tif len(res.Failures) != 1 {\n\t\tt.Errorf(\"failures length should be 1, got %d\", len(res.Failures))\n\t}\n\texpected := bulkIndexByScrollResponseFailure{Index: \"a\", Type: \"_doc\", Id: \"yjsmdGsBm363wfQmSbhj\", Status: 409}\n\tif res.Failures[0] != expected {\n\t\tt.Errorf(\"failures should be %+v, got %+v\", expected, res.Failures[0])\n\t}\n}\n"
  },
  {
    "path": "update_integration_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc TestUpdateWithDoc(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Get original\n\tgetRes, err := client.Get().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar original tweet\n\tif err := json.Unmarshal(getRes.Source, &original); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Partial update\n\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\tdefer cancel()\n\tupdRes, err := client.Update().\n\t\tIndex(testIndexName).\n\t\tId(\"1\").\n\t\tDoc(map[string]interface{}{\n\t\t\t\"message\": \"Updated message text.\",\n\t\t}).\n\t\tDo(ctx)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif updRes == nil {\n\t\tt.Fatal(\"response is nil\")\n\t}\n\tif want, have := \"updated\", updRes.Result; want != have {\n\t\tt.Fatalf(\"want Result = %q, have %v\", want, have)\n\t}\n\n\t// Get new version\n\tgetRes, err = client.Get().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar updated tweet\n\tif err := json.Unmarshal(getRes.Source, &updated); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif want, have := original.User, updated.User; want != have {\n\t\tt.Fatalf(\"want User = %q, have %v\", want, have)\n\t}\n\tif want, have := \"Updated message text.\", updated.Message; want != have {\n\t\tt.Fatalf(\"want Message = %q, have %v\", want, have)\n\t}\n}\n\nfunc TestUpdateWithScript(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Get original\n\tgetRes, err := client.Get().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar original tweet\n\tif err := json.Unmarshal(getRes.Source, &original); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Update with script\n\tupdRes, err := client.Update().Index(testIndexName).Id(\"1\").\n\t\tScript(\n\t\t\tNewScript(`ctx._source.message = \"Updated message text.\"`).Lang(\"painless\"),\n\t\t).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif updRes == nil {\n\t\tt.Fatal(\"response is nil\")\n\t}\n\tif want, have := \"updated\", updRes.Result; want != have {\n\t\tt.Fatalf(\"want Result = %q, have %v\", want, have)\n\t}\n\n\t// Get new version\n\tgetRes, err = client.Get().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar updated tweet\n\tif err := json.Unmarshal(getRes.Source, &updated); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif want, have := original.User, updated.User; want != have {\n\t\tt.Fatalf(\"want User = %q, have %v\", want, have)\n\t}\n\tif want, have := \"Updated message text.\", updated.Message; want != have {\n\t\tt.Fatalf(\"want Message = %q, have %v\", want, have)\n\t}\n}\n\nfunc TestUpdateWithScriptID(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\t// Get original\n\tgetRes, err := client.Get().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar original tweet\n\tif err := json.Unmarshal(getRes.Source, &original); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Set script with ID\n\tscriptID := \"example-script-id\"\n\t_, err = client.DeleteScript().Id(scriptID).Do(context.Background())\n\tif err != nil && !IsNotFound(err) {\n\t\tt.Fatal(err)\n\t}\n\t_, err = client.PutScript().\n\t\tId(scriptID).\n\t\tBodyString(`{\n\t\t\t\"script\": {\n\t\t\t\t\"lang\": \"painless\",\n\t\t\t\t\"source\": \"ctx._source.message = params.new_message\"\n\t\t\t}\n\t\t}`).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\t// Update with script\n\tupdRes, err := client.Update().Index(testIndexName).Id(\"1\").\n\t\tScript(\n\t\t\tNewScriptStored(scriptID).Param(\"new_message\", \"Updated message text.\"),\n\t\t).\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif updRes == nil {\n\t\tt.Fatal(\"response is nil\")\n\t}\n\tif want, have := \"updated\", updRes.Result; want != have {\n\t\tt.Fatalf(\"want Result = %q, have %v\", want, have)\n\t}\n\n\t// Get new version\n\tgetRes, err = client.Get().Index(testIndexName).Id(\"1\").Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tvar updated tweet\n\tif err := json.Unmarshal(getRes.Source, &updated); err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif want, have := original.User, updated.User; want != have {\n\t\tt.Fatalf(\"want User = %q, have %v\", want, have)\n\t}\n\tif want, have := \"Updated message text.\", updated.Message; want != have {\n\t\tt.Fatalf(\"want Message = %q, have %v\", want, have)\n\t}\n}\n"
  },
  {
    "path": "update_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/url\"\n\t\"testing\"\n)\n\nfunc TestUpdateViaScript(t *testing.T) {\n\tclient := setupTestClient(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tupdate := client.Update().\n\t\tIndex(\"test\").Type(\"type1\").Id(\"1\").\n\t\tScript(NewScript(\"ctx._source.tags += params.tag\").Params(map[string]interface{}{\"tag\": \"blue\"}).Lang(\"groovy\"))\n\tpath, params, err := update.url()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return URL, got: %v\", err)\n\t}\n\texpectedPath := `/test/type1/1/_update`\n\tif expectedPath != path {\n\t\tt.Errorf(\"expected URL path\\n%s\\ngot:\\n%s\", expectedPath, path)\n\t}\n\texpectedParams := url.Values{}\n\tif expectedParams.Encode() != params.Encode() {\n\t\tt.Errorf(\"expected URL parameters\\n%s\\ngot:\\n%s\", expectedParams.Encode(), params.Encode())\n\t}\n\tbody, err := update.body()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return body, got: %v\", err)\n\t}\n\tdata, err := json.Marshal(body)\n\tif err != nil {\n\t\tt.Fatalf(\"expected to marshal body as JSON, got: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"script\":{\"lang\":\"groovy\",\"params\":{\"tag\":\"blue\"},\"source\":\"ctx._source.tags += params.tag\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\ngot:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestUpdateViaScriptId(t *testing.T) {\n\tclient := setupTestClient(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tscriptParams := map[string]interface{}{\n\t\t\"pageViewEvent\": map[string]interface{}{\n\t\t\t\"url\":      \"foo.com/bar\",\n\t\t\t\"response\": 404,\n\t\t\t\"time\":     \"2014-01-01 12:32\",\n\t\t},\n\t}\n\tscript := NewScriptStored(\"my_web_session_summariser\").Params(scriptParams)\n\n\tupdate := client.Update().\n\t\tIndex(\"sessions\").Type(\"session\").Id(\"dh3sgudg8gsrgl\").\n\t\tScript(script).\n\t\tScriptedUpsert(true).\n\t\tUpsert(map[string]interface{}{})\n\tpath, params, err := update.url()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return URL, got: %v\", err)\n\t}\n\texpectedPath := `/sessions/session/dh3sgudg8gsrgl/_update`\n\tif expectedPath != path {\n\t\tt.Errorf(\"expected URL path\\n%s\\ngot:\\n%s\", expectedPath, path)\n\t}\n\texpectedParams := url.Values{}\n\tif expectedParams.Encode() != params.Encode() {\n\t\tt.Errorf(\"expected URL parameters\\n%s\\ngot:\\n%s\", expectedParams.Encode(), params.Encode())\n\t}\n\tbody, err := update.body()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return body, got: %v\", err)\n\t}\n\tdata, err := json.Marshal(body)\n\tif err != nil {\n\t\tt.Fatalf(\"expected to marshal body as JSON, got: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"script\":{\"id\":\"my_web_session_summariser\",\"params\":{\"pageViewEvent\":{\"response\":404,\"time\":\"2014-01-01 12:32\",\"url\":\"foo.com/bar\"}}},\"scripted_upsert\":true,\"upsert\":{}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\ngot:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestUpdateViaScriptAndUpsert(t *testing.T) {\n\tclient := setupTestClient(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tupdate := client.Update().\n\t\tIndex(\"test\").Type(\"type1\").Id(\"1\").\n\t\tScript(NewScript(\"ctx._source.counter += params.count\").Params(map[string]interface{}{\"count\": 4})).\n\t\tUpsert(map[string]interface{}{\"counter\": 1})\n\tpath, params, err := update.url()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return URL, got: %v\", err)\n\t}\n\texpectedPath := `/test/type1/1/_update`\n\tif expectedPath != path {\n\t\tt.Errorf(\"expected URL path\\n%s\\ngot:\\n%s\", expectedPath, path)\n\t}\n\texpectedParams := url.Values{}\n\tif expectedParams.Encode() != params.Encode() {\n\t\tt.Errorf(\"expected URL parameters\\n%s\\ngot:\\n%s\", expectedParams.Encode(), params.Encode())\n\t}\n\tbody, err := update.body()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return body, got: %v\", err)\n\t}\n\tdata, err := json.Marshal(body)\n\tif err != nil {\n\t\tt.Fatalf(\"expected to marshal body as JSON, got: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"script\":{\"params\":{\"count\":4},\"source\":\"ctx._source.counter += params.count\"},\"upsert\":{\"counter\":1}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\ngot:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestUpdateViaDoc(t *testing.T) {\n\tclient := setupTestClient(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tupdate := client.Update().\n\t\tIndex(\"test\").Type(\"type1\").Id(\"1\").\n\t\tDoc(map[string]interface{}{\"name\": \"new_name\"}).\n\t\tDetectNoop(true)\n\tpath, params, err := update.url()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return URL, got: %v\", err)\n\t}\n\texpectedPath := `/test/type1/1/_update`\n\tif expectedPath != path {\n\t\tt.Errorf(\"expected URL path\\n%s\\ngot:\\n%s\", expectedPath, path)\n\t}\n\texpectedParams := url.Values{}\n\tif expectedParams.Encode() != params.Encode() {\n\t\tt.Errorf(\"expected URL parameters\\n%s\\ngot:\\n%s\", expectedParams.Encode(), params.Encode())\n\t}\n\tbody, err := update.body()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return body, got: %v\", err)\n\t}\n\tdata, err := json.Marshal(body)\n\tif err != nil {\n\t\tt.Fatalf(\"expected to marshal body as JSON, got: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"detect_noop\":true,\"doc\":{\"name\":\"new_name\"}}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\ngot:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestUpdateViaDocAndUpsert(t *testing.T) {\n\tclient := setupTestClient(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tupdate := client.Update().\n\t\tIndex(\"test\").Type(\"type1\").Id(\"1\").\n\t\tDoc(map[string]interface{}{\"name\": \"new_name\"}).\n\t\tDocAsUpsert(true).\n\t\tTimeout(\"1s\").\n\t\tRefresh(\"true\")\n\tpath, params, err := update.url()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return URL, got: %v\", err)\n\t}\n\texpectedPath := `/test/type1/1/_update`\n\tif expectedPath != path {\n\t\tt.Errorf(\"expected URL path\\n%s\\ngot:\\n%s\", expectedPath, path)\n\t}\n\texpectedParams := url.Values{\"refresh\": []string{\"true\"}, \"timeout\": []string{\"1s\"}}\n\tif expectedParams.Encode() != params.Encode() {\n\t\tt.Errorf(\"expected URL parameters\\n%s\\ngot:\\n%s\", expectedParams.Encode(), params.Encode())\n\t}\n\tbody, err := update.body()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return body, got: %v\", err)\n\t}\n\tdata, err := json.Marshal(body)\n\tif err != nil {\n\t\tt.Fatalf(\"expected to marshal body as JSON, got: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"doc\":{\"name\":\"new_name\"},\"doc_as_upsert\":true}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\ngot:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestUpdateViaDocAndUpsertAndFetchSource(t *testing.T) {\n\tclient := setupTestClient(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tupdate := client.Update().\n\t\tIndex(\"test\").Type(\"type1\").Id(\"1\").\n\t\tDoc(map[string]interface{}{\"name\": \"new_name\"}).\n\t\tDocAsUpsert(true).\n\t\tTimeout(\"1s\").\n\t\tRefresh(\"true\").\n\t\tFetchSource(true)\n\tpath, params, err := update.url()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return URL, got: %v\", err)\n\t}\n\texpectedPath := `/test/type1/1/_update`\n\tif expectedPath != path {\n\t\tt.Errorf(\"expected URL path\\n%s\\ngot:\\n%s\", expectedPath, path)\n\t}\n\texpectedParams := url.Values{\n\t\t\"refresh\": []string{\"true\"},\n\t\t\"timeout\": []string{\"1s\"},\n\t}\n\tif expectedParams.Encode() != params.Encode() {\n\t\tt.Errorf(\"expected URL parameters\\n%s\\ngot:\\n%s\", expectedParams.Encode(), params.Encode())\n\t}\n\tbody, err := update.body()\n\tif err != nil {\n\t\tt.Fatalf(\"expected to return body, got: %v\", err)\n\t}\n\tdata, err := json.Marshal(body)\n\tif err != nil {\n\t\tt.Fatalf(\"expected to marshal body as JSON, got: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"_source\":true,\"doc\":{\"name\":\"new_name\"},\"doc_as_upsert\":true}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\ngot:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestUpdateAndFetchSource(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tres, err := client.Update().\n\t\tIndex(testIndexName).Id(\"1\").\n\t\tDoc(map[string]interface{}{\"user\": \"sandrae\"}).\n\t\tDetectNoop(true).\n\t\tFetchSource(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response != nil\")\n\t}\n\tif res.GetResult == nil {\n\t\tt.Fatal(\"expected GetResult != nil\")\n\t}\n\tdata, err := json.Marshal(res.GetResult.Source)\n\tif err != nil {\n\t\tt.Fatalf(\"expected to marshal body as JSON, got: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"user\":\"sandrae\",\"message\":\"Welcome to Golang and Elasticsearch.\",\"retweets\":108,\"created\":\"0001-01-01T00:00:00Z\",\"tags\":[\"golang\",\"elasticsearch\"]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\ngot:\\n%s\", expected, got)\n\t}\n}\n\nfunc TestUpdateOptimistic(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\tdoc, err := client.Get().\n\t\tIndex(testIndexName).Id(\"1\").\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif doc.SeqNo == nil {\n\t\tt.Fatal(\"expected seq_no != nil\")\n\t}\n\tif doc.PrimaryTerm == nil {\n\t\tt.Fatal(\"expected primary_term != nil\")\n\t}\n\n\t// Update with seqNo != doc.SeqNo and primaryTerm != doc.PrimaryTerm\n\t_, err = client.Update().\n\t\tIndex(testIndexName).Id(doc.Id).\n\t\tDoc(map[string]interface{}{\"user\": \"sandrae\"}).\n\t\tIfSeqNo(*doc.SeqNo + 1000).\n\t\tIfPrimaryTerm(*doc.PrimaryTerm + 1000).\n\t\tDo(context.Background())\n\tif err == nil {\n\t\tt.Fatal(\"expected error, got nil\")\n\t}\n\tif !IsConflict(err) {\n\t\tt.Fatalf(\"expected conflict error, got %v (%T)\", err, err)\n\t}\n\n\t// Update with seqNo == doc.SeqNo and primaryTerm == doc.PrimaryTerm\n\tres, err := client.Update().\n\t\tIndex(testIndexName).Id(doc.Id).\n\t\tDoc(map[string]interface{}{\"user\": \"sandrae\"}).\n\t\tIfSeqNo(*doc.SeqNo).\n\t\tIfPrimaryTerm(*doc.PrimaryTerm).\n\t\tFetchSource(true).\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif res == nil {\n\t\tt.Fatal(\"expected response != nil\")\n\t}\n\tif res.GetResult == nil {\n\t\tt.Fatal(\"expected GetResult != nil\")\n\t}\n\tdata, err := json.Marshal(res.GetResult.Source)\n\tif err != nil {\n\t\tt.Fatalf(\"expected to marshal body as JSON, got: %v\", err)\n\t}\n\tgot := string(data)\n\texpected := `{\"user\":\"sandrae\",\"message\":\"Welcome to Golang and Elasticsearch.\",\"retweets\":108,\"created\":\"0001-01-01T00:00:00Z\",\"tags\":[\"golang\",\"elasticsearch\"]}`\n\tif got != expected {\n\t\tt.Errorf(\"expected\\n%s\\ngot:\\n%s\", expected, got)\n\t}\n}\n"
  },
  {
    "path": "uritemplates/LICENSE",
    "content": "Copyright (c) 2013 Joshua Tacoma\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "uritemplates/uritemplates.go",
    "content": "// Copyright 2013 Joshua Tacoma. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// Package uritemplates is a level 4 implementation of RFC 6570 (URI\n// Template, http://tools.ietf.org/html/rfc6570).\n//\n// To use uritemplates, parse a template string and expand it with a value\n// map:\n//\n//\ttemplate, _ := uritemplates.Parse(\"https://api.github.com/repos{/user,repo}\")\n//\tvalues := make(map[string]interface{})\n//\tvalues[\"user\"] = \"jtacoma\"\n//\tvalues[\"repo\"] = \"uritemplates\"\n//\texpanded, _ := template.Expand(values)\n//\tfmt.Printf(expanded)\n//\npackage uritemplates\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nvar (\n\tunreserved = regexp.MustCompile(\"[^A-Za-z0-9\\\\-._~]\")\n\treserved   = regexp.MustCompile(\"[^A-Za-z0-9\\\\-._~:/?#[\\\\]@!$&'()*+,;=]\")\n\tvalidname  = regexp.MustCompile(\"^([A-Za-z0-9_\\\\.]|%[0-9A-Fa-f][0-9A-Fa-f])+$\")\n\thex        = []byte(\"0123456789ABCDEF\")\n)\n\nfunc pctEncode(src []byte) []byte {\n\tdst := make([]byte, len(src)*3)\n\tfor i, b := range src {\n\t\tbuf := dst[i*3 : i*3+3]\n\t\tbuf[0] = 0x25\n\t\tbuf[1] = hex[b/16]\n\t\tbuf[2] = hex[b%16]\n\t}\n\treturn dst\n}\n\nfunc escape(s string, allowReserved bool) (escaped string) {\n\tif allowReserved {\n\t\tescaped = string(reserved.ReplaceAllFunc([]byte(s), pctEncode))\n\t} else {\n\t\tescaped = string(unreserved.ReplaceAllFunc([]byte(s), pctEncode))\n\t}\n\treturn escaped\n}\n\n// A UriTemplate is a parsed representation of a URI template.\ntype UriTemplate struct {\n\traw   string\n\tparts []templatePart\n}\n\n// Parse parses a URI template string into a UriTemplate object.\nfunc Parse(rawtemplate string) (template *UriTemplate, err error) {\n\ttemplate = new(UriTemplate)\n\ttemplate.raw = rawtemplate\n\tsplit := strings.Split(rawtemplate, \"{\")\n\ttemplate.parts = make([]templatePart, len(split)*2-1)\n\tfor i, s := range split {\n\t\tif i == 0 {\n\t\t\tif strings.Contains(s, \"}\") {\n\t\t\t\terr = errors.New(\"unexpected }\")\n\t\t\t\tbreak\n\t\t\t}\n\t\t\ttemplate.parts[i].raw = s\n\t\t} else {\n\t\t\tsubsplit := strings.Split(s, \"}\")\n\t\t\tif len(subsplit) != 2 {\n\t\t\t\terr = errors.New(\"malformed template\")\n\t\t\t\tbreak\n\t\t\t}\n\t\t\texpression := subsplit[0]\n\t\t\ttemplate.parts[i*2-1], err = parseExpression(expression)\n\t\t\tif err != nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\ttemplate.parts[i*2].raw = subsplit[1]\n\t\t}\n\t}\n\tif err != nil {\n\t\ttemplate = nil\n\t}\n\treturn template, err\n}\n\ntype templatePart struct {\n\traw           string\n\tterms         []templateTerm\n\tfirst         string\n\tsep           string\n\tnamed         bool\n\tifemp         string\n\tallowReserved bool\n}\n\ntype templateTerm struct {\n\tname     string\n\texplode  bool\n\ttruncate int\n}\n\nfunc parseExpression(expression string) (result templatePart, err error) {\n\tswitch expression[0] {\n\tcase '+':\n\t\tresult.sep = \",\"\n\t\tresult.allowReserved = true\n\t\texpression = expression[1:]\n\tcase '.':\n\t\tresult.first = \".\"\n\t\tresult.sep = \".\"\n\t\texpression = expression[1:]\n\tcase '/':\n\t\tresult.first = \"/\"\n\t\tresult.sep = \"/\"\n\t\texpression = expression[1:]\n\tcase ';':\n\t\tresult.first = \";\"\n\t\tresult.sep = \";\"\n\t\tresult.named = true\n\t\texpression = expression[1:]\n\tcase '?':\n\t\tresult.first = \"?\"\n\t\tresult.sep = \"&\"\n\t\tresult.named = true\n\t\tresult.ifemp = \"=\"\n\t\texpression = expression[1:]\n\tcase '&':\n\t\tresult.first = \"&\"\n\t\tresult.sep = \"&\"\n\t\tresult.named = true\n\t\tresult.ifemp = \"=\"\n\t\texpression = expression[1:]\n\tcase '#':\n\t\tresult.first = \"#\"\n\t\tresult.sep = \",\"\n\t\tresult.allowReserved = true\n\t\texpression = expression[1:]\n\tdefault:\n\t\tresult.sep = \",\"\n\t}\n\trawterms := strings.Split(expression, \",\")\n\tresult.terms = make([]templateTerm, len(rawterms))\n\tfor i, raw := range rawterms {\n\t\tresult.terms[i], err = parseTerm(raw)\n\t\tif err != nil {\n\t\t\tbreak\n\t\t}\n\t}\n\treturn result, err\n}\n\nfunc parseTerm(term string) (result templateTerm, err error) {\n\tif strings.HasSuffix(term, \"*\") {\n\t\tresult.explode = true\n\t\tterm = term[:len(term)-1]\n\t}\n\tsplit := strings.Split(term, \":\")\n\tif len(split) == 1 {\n\t\tresult.name = term\n\t} else if len(split) == 2 {\n\t\tresult.name = split[0]\n\t\tvar parsed int64\n\t\tparsed, err = strconv.ParseInt(split[1], 10, 0)\n\t\tresult.truncate = int(parsed)\n\t} else {\n\t\terr = errors.New(\"multiple colons in same term\")\n\t}\n\tif !validname.MatchString(result.name) {\n\t\terr = errors.New(\"not a valid name: \" + result.name)\n\t}\n\tif result.explode && result.truncate > 0 {\n\t\terr = errors.New(\"both explode and prefix modifers on same term\")\n\t}\n\treturn result, err\n}\n\n// Expand expands a URI template with a set of values to produce a string.\nfunc (self *UriTemplate) Expand(value interface{}) (string, error) {\n\tvalues, ismap := value.(map[string]interface{})\n\tif !ismap {\n\t\tif m, ismap := struct2map(value); !ismap {\n\t\t\treturn \"\", errors.New(\"expected map[string]interface{}, struct, or pointer to struct.\")\n\t\t} else {\n\t\t\treturn self.Expand(m)\n\t\t}\n\t}\n\tvar buf bytes.Buffer\n\tfor _, p := range self.parts {\n\t\terr := p.expand(&buf, values)\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t}\n\treturn buf.String(), nil\n}\n\nfunc (self *templatePart) expand(buf *bytes.Buffer, values map[string]interface{}) error {\n\tif len(self.raw) > 0 {\n\t\tbuf.WriteString(self.raw)\n\t\treturn nil\n\t}\n\tvar zeroLen = buf.Len()\n\tbuf.WriteString(self.first)\n\tvar firstLen = buf.Len()\n\tfor _, term := range self.terms {\n\t\tvalue, exists := values[term.name]\n\t\tif !exists {\n\t\t\tcontinue\n\t\t}\n\t\tif buf.Len() != firstLen {\n\t\t\tbuf.WriteString(self.sep)\n\t\t}\n\t\tswitch v := value.(type) {\n\t\tcase string:\n\t\t\tself.expandString(buf, term, v)\n\t\tcase []interface{}:\n\t\t\tself.expandArray(buf, term, v)\n\t\tcase map[string]interface{}:\n\t\t\tif term.truncate > 0 {\n\t\t\t\treturn errors.New(\"cannot truncate a map expansion\")\n\t\t\t}\n\t\t\tself.expandMap(buf, term, v)\n\t\tdefault:\n\t\t\tif m, ismap := struct2map(value); ismap {\n\t\t\t\tif term.truncate > 0 {\n\t\t\t\t\treturn errors.New(\"cannot truncate a map expansion\")\n\t\t\t\t}\n\t\t\t\tself.expandMap(buf, term, m)\n\t\t\t} else {\n\t\t\t\tstr := fmt.Sprintf(\"%v\", value)\n\t\t\t\tself.expandString(buf, term, str)\n\t\t\t}\n\t\t}\n\t}\n\tif buf.Len() == firstLen {\n\t\toriginal := buf.Bytes()[:zeroLen]\n\t\tbuf.Reset()\n\t\tbuf.Write(original)\n\t}\n\treturn nil\n}\n\nfunc (self *templatePart) expandName(buf *bytes.Buffer, name string, empty bool) {\n\tif self.named {\n\t\tbuf.WriteString(name)\n\t\tif empty {\n\t\t\tbuf.WriteString(self.ifemp)\n\t\t} else {\n\t\t\tbuf.WriteString(\"=\")\n\t\t}\n\t}\n}\n\nfunc (self *templatePart) expandString(buf *bytes.Buffer, t templateTerm, s string) {\n\tif len(s) > t.truncate && t.truncate > 0 {\n\t\ts = s[:t.truncate]\n\t}\n\tself.expandName(buf, t.name, len(s) == 0)\n\tbuf.WriteString(escape(s, self.allowReserved))\n}\n\nfunc (self *templatePart) expandArray(buf *bytes.Buffer, t templateTerm, a []interface{}) {\n\tif len(a) == 0 {\n\t\treturn\n\t} else if !t.explode {\n\t\tself.expandName(buf, t.name, false)\n\t}\n\tfor i, value := range a {\n\t\tif t.explode && i > 0 {\n\t\t\tbuf.WriteString(self.sep)\n\t\t} else if i > 0 {\n\t\t\tbuf.WriteString(\",\")\n\t\t}\n\t\tvar s string\n\t\tswitch v := value.(type) {\n\t\tcase string:\n\t\t\ts = v\n\t\tdefault:\n\t\t\ts = fmt.Sprintf(\"%v\", v)\n\t\t}\n\t\tif len(s) > t.truncate && t.truncate > 0 {\n\t\t\ts = s[:t.truncate]\n\t\t}\n\t\tif self.named && t.explode {\n\t\t\tself.expandName(buf, t.name, len(s) == 0)\n\t\t}\n\t\tbuf.WriteString(escape(s, self.allowReserved))\n\t}\n}\n\nfunc (self *templatePart) expandMap(buf *bytes.Buffer, t templateTerm, m map[string]interface{}) {\n\tif len(m) == 0 {\n\t\treturn\n\t}\n\tif !t.explode {\n\t\tself.expandName(buf, t.name, len(m) == 0)\n\t}\n\tvar firstLen = buf.Len()\n\tfor k, value := range m {\n\t\tif firstLen != buf.Len() {\n\t\t\tif t.explode {\n\t\t\t\tbuf.WriteString(self.sep)\n\t\t\t} else {\n\t\t\t\tbuf.WriteString(\",\")\n\t\t\t}\n\t\t}\n\t\tvar s string\n\t\tswitch v := value.(type) {\n\t\tcase string:\n\t\t\ts = v\n\t\tdefault:\n\t\t\ts = fmt.Sprintf(\"%v\", v)\n\t\t}\n\t\tif t.explode {\n\t\t\tbuf.WriteString(escape(k, self.allowReserved))\n\t\t\tbuf.WriteRune('=')\n\t\t\tbuf.WriteString(escape(s, self.allowReserved))\n\t\t} else {\n\t\t\tbuf.WriteString(escape(k, self.allowReserved))\n\t\t\tbuf.WriteRune(',')\n\t\t\tbuf.WriteString(escape(s, self.allowReserved))\n\t\t}\n\t}\n}\n\nfunc struct2map(v interface{}) (map[string]interface{}, bool) {\n\tvalue := reflect.ValueOf(v)\n\tswitch value.Type().Kind() {\n\tcase reflect.Ptr:\n\t\treturn struct2map(value.Elem().Interface())\n\tcase reflect.Struct:\n\t\tm := make(map[string]interface{})\n\t\tfor i := 0; i < value.NumField(); i++ {\n\t\t\ttag := value.Type().Field(i).Tag\n\t\t\tvar name string\n\t\t\tif strings.Contains(string(tag), \":\") {\n\t\t\t\tname = tag.Get(\"uri\")\n\t\t\t} else {\n\t\t\t\tname = strings.TrimSpace(string(tag))\n\t\t\t}\n\t\t\tif len(name) == 0 {\n\t\t\t\tname = value.Type().Field(i).Name\n\t\t\t}\n\t\t\tm[name] = value.Field(i).Interface()\n\t\t}\n\t\treturn m, true\n\t}\n\treturn nil, false\n}\n"
  },
  {
    "path": "uritemplates/utils.go",
    "content": "package uritemplates\n\nfunc Expand(path string, expansions map[string]string) (string, error) {\n\ttemplate, err := Parse(path)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tvalues := make(map[string]interface{})\n\tfor k, v := range expansions {\n\t\tvalues[k] = v\n\t}\n\treturn template.Expand(values)\n}\n"
  },
  {
    "path": "uritemplates/utils_test.go",
    "content": "package uritemplates\n\nimport (\n\t\"testing\"\n)\n\ntype ExpandTest struct {\n\tin         string\n\texpansions map[string]string\n\twant       string\n}\n\nvar expandTests = []ExpandTest{\n\t// #0: no expansions\n\t{\n\t\t\"http://www.golang.org/\",\n\t\tmap[string]string{},\n\t\t\"http://www.golang.org/\",\n\t},\n\t// #1: one expansion, no escaping\n\t{\n\t\t\"http://www.golang.org/{bucket}/delete\",\n\t\tmap[string]string{\n\t\t\t\"bucket\": \"red\",\n\t\t},\n\t\t\"http://www.golang.org/red/delete\",\n\t},\n\t// #2: one expansion, with hex escapes\n\t{\n\t\t\"http://www.golang.org/{bucket}/delete\",\n\t\tmap[string]string{\n\t\t\t\"bucket\": \"red/blue\",\n\t\t},\n\t\t\"http://www.golang.org/red%2Fblue/delete\",\n\t},\n\t// #3: one expansion, with space\n\t{\n\t\t\"http://www.golang.org/{bucket}/delete\",\n\t\tmap[string]string{\n\t\t\t\"bucket\": \"red or blue\",\n\t\t},\n\t\t\"http://www.golang.org/red%20or%20blue/delete\",\n\t},\n\t// #4: expansion not found\n\t{\n\t\t\"http://www.golang.org/{object}/delete\",\n\t\tmap[string]string{\n\t\t\t\"bucket\": \"red or blue\",\n\t\t},\n\t\t\"http://www.golang.org//delete\",\n\t},\n\t// #5: multiple expansions\n\t{\n\t\t\"http://www.golang.org/{one}/{two}/{three}/get\",\n\t\tmap[string]string{\n\t\t\t\"one\":   \"ONE\",\n\t\t\t\"two\":   \"TWO\",\n\t\t\t\"three\": \"THREE\",\n\t\t},\n\t\t\"http://www.golang.org/ONE/TWO/THREE/get\",\n\t},\n\t// #6: utf-8 characters\n\t{\n\t\t\"http://www.golang.org/{bucket}/get\",\n\t\tmap[string]string{\n\t\t\t\"bucket\": \"£100\",\n\t\t},\n\t\t\"http://www.golang.org/%C2%A3100/get\",\n\t},\n\t// #7: punctuations\n\t{\n\t\t\"http://www.golang.org/{bucket}/get\",\n\t\tmap[string]string{\n\t\t\t\"bucket\": `/\\@:,.*~`,\n\t\t},\n\t\t\"http://www.golang.org/%2F%5C%40%3A%2C.%2A~/get\",\n\t},\n\t// #8: mis-matched brackets\n\t{\n\t\t\"http://www.golang.org/{bucket/get\",\n\t\tmap[string]string{\n\t\t\t\"bucket\": \"red\",\n\t\t},\n\t\t\"\",\n\t},\n\t// #9: \"+\" prefix for suppressing escape\n\t// See also: http://tools.ietf.org/html/rfc6570#section-3.2.3\n\t{\n\t\t\"http://www.golang.org/{+topic}\",\n\t\tmap[string]string{\n\t\t\t\"topic\": \"/topics/myproject/mytopic\",\n\t\t},\n\t\t// The double slashes here look weird, but it's intentional\n\t\t\"http://www.golang.org//topics/myproject/mytopic\",\n\t},\n}\n\nfunc TestExpand(t *testing.T) {\n\tfor i, test := range expandTests {\n\t\tgot, _ := Expand(test.in, test.expansions)\n\t\tif got != test.want {\n\t\t\tt.Errorf(\"got %q expected %q in test %d\", got, test.want, i)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "validate.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// ValidateService allows a user to validate a potentially\n// expensive query without executing it.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-validate.html.\ntype ValidateService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tindex             []string\n\ttyp               []string\n\tq                 string\n\texplain           *bool\n\trewrite           *bool\n\tallShards         *bool\n\tlenient           *bool\n\tanalyzer          string\n\tdf                string\n\tanalyzeWildcard   *bool\n\tdefaultOperator   string\n\tignoreUnavailable *bool\n\tallowNoIndices    *bool\n\texpandWildcards   string\n\tbodyJson          interface{}\n\tbodyString        string\n}\n\n// NewValidateService creates a new ValidateService.\nfunc NewValidateService(client *Client) *ValidateService {\n\treturn &ValidateService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *ValidateService) Pretty(pretty bool) *ValidateService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *ValidateService) Human(human bool) *ValidateService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *ValidateService) ErrorTrace(errorTrace bool) *ValidateService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *ValidateService) FilterPath(filterPath ...string) *ValidateService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *ValidateService) Header(name string, value string) *ValidateService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *ValidateService) Headers(headers http.Header) *ValidateService {\n\ts.headers = headers\n\treturn s\n}\n\n// Index sets the names of the indices to use for search.\nfunc (s *ValidateService) Index(index ...string) *ValidateService {\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// Type adds search restrictions for a list of types.\n//\n// Deprecated: Types are in the process of being removed. Instead of using a type, prefer to\n// filter on a field on the document.\nfunc (s *ValidateService) Type(typ ...string) *ValidateService {\n\ts.typ = append(s.typ, typ...)\n\treturn s\n}\n\n// Lenient specifies whether format-based query failures\n// (such as providing text to a numeric field) should be ignored.\nfunc (s *ValidateService) Lenient(lenient bool) *ValidateService {\n\ts.lenient = &lenient\n\treturn s\n}\n\n// Query in the Lucene query string syntax.\nfunc (s *ValidateService) Q(q string) *ValidateService {\n\ts.q = q\n\treturn s\n}\n\n// An explain parameter can be specified to get more detailed information about why a query failed.\nfunc (s *ValidateService) Explain(explain *bool) *ValidateService {\n\ts.explain = explain\n\treturn s\n}\n\n// Provide a more detailed explanation showing the actual Lucene query that will be executed.\nfunc (s *ValidateService) Rewrite(rewrite *bool) *ValidateService {\n\ts.rewrite = rewrite\n\treturn s\n}\n\n// Execute validation on all shards instead of one random shard per index.\nfunc (s *ValidateService) AllShards(allShards *bool) *ValidateService {\n\ts.allShards = allShards\n\treturn s\n}\n\n// AnalyzeWildcard specifies whether wildcards and prefix queries\n// in the query string query should be analyzed (default: false).\nfunc (s *ValidateService) AnalyzeWildcard(analyzeWildcard bool) *ValidateService {\n\ts.analyzeWildcard = &analyzeWildcard\n\treturn s\n}\n\n// Analyzer is the analyzer for the query string query.\nfunc (s *ValidateService) Analyzer(analyzer string) *ValidateService {\n\ts.analyzer = analyzer\n\treturn s\n}\n\n// Df is the default field for query string query (default: _all).\nfunc (s *ValidateService) Df(df string) *ValidateService {\n\ts.df = df\n\treturn s\n}\n\n// DefaultOperator is the default operator for query string query (AND or OR).\nfunc (s *ValidateService) DefaultOperator(defaultOperator string) *ValidateService {\n\ts.defaultOperator = defaultOperator\n\treturn s\n}\n\n// Query sets a query definition using the Query DSL.\nfunc (s *ValidateService) Query(query Query) *ValidateService {\n\tsrc, err := query.Source()\n\tif err != nil {\n\t\t// Do nothing in case of an error\n\t\treturn s\n\t}\n\tbody := make(map[string]interface{})\n\tbody[\"query\"] = src\n\ts.bodyJson = body\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether the specified concrete indices\n// should be ignored when unavailable (missing or closed).\nfunc (s *ValidateService) IgnoreUnavailable(ignoreUnavailable bool) *ValidateService {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes `_all` string\n// or when no indices have been specified).\nfunc (s *ValidateService) AllowNoIndices(allowNoIndices bool) *ValidateService {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *ValidateService) ExpandWildcards(expandWildcards string) *ValidateService {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// BodyJson sets the query definition using the Query DSL.\nfunc (s *ValidateService) BodyJson(body interface{}) *ValidateService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString sets the query definition using the Query DSL as a string.\nfunc (s *ValidateService) BodyString(body string) *ValidateService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *ValidateService) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\t// Build URL\n\tif len(s.index) > 0 && len(s.typ) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/_validate/query\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t\t\"type\":  strings.Join(s.typ, \",\"),\n\t\t})\n\t} else if len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_validate/query\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/_validate/query\", map[string]string{\n\t\t\t\"type\": strings.Join(s.typ, \",\"),\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.explain != nil {\n\t\tparams.Set(\"explain\", fmt.Sprintf(\"%v\", *s.explain))\n\t}\n\tif s.rewrite != nil {\n\t\tparams.Set(\"rewrite\", fmt.Sprintf(\"%v\", *s.rewrite))\n\t}\n\tif s.allShards != nil {\n\t\tparams.Set(\"all_shards\", fmt.Sprintf(\"%v\", *s.allShards))\n\t}\n\tif s.defaultOperator != \"\" {\n\t\tparams.Set(\"default_operator\", s.defaultOperator)\n\t}\n\tif v := s.lenient; v != nil {\n\t\tparams.Set(\"lenient\", fmt.Sprint(*v))\n\t}\n\tif s.q != \"\" {\n\t\tparams.Set(\"q\", s.q)\n\t}\n\tif v := s.analyzeWildcard; v != nil {\n\t\tparams.Set(\"analyze_wildcard\", fmt.Sprint(*v))\n\t}\n\tif s.analyzer != \"\" {\n\t\tparams.Set(\"analyzer\", s.analyzer)\n\t}\n\tif s.df != \"\" {\n\t\tparams.Set(\"df\", s.df)\n\t}\n\tif v := s.allowNoIndices; v != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprint(*v))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif v := s.ignoreUnavailable; v != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *ValidateService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *ValidateService) Do(ctx context.Context) (*ValidateResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(ValidateResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// ValidateResponse is the response of ValidateService.Do.\ntype ValidateResponse struct {\n\tValid        bool                   `json:\"valid\"`\n\tShards       map[string]interface{} `json:\"_shards\"`\n\tExplanations []interface{}          `json:\"explanations\"`\n}\n"
  },
  {
    "path": "validate_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestValidate(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t)\n\n\ttweet1 := tweet{User: \"olivere\", Message: \"Welcome to Golang and Elasticsearch.\"}\n\n\t// Add a document\n\tindexResult, err := client.Index().\n\t\tIndex(testIndexName).\n\t\tBodyJson(&tweet1).\n\t\tRefresh(\"true\").\n\t\tDo(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif indexResult == nil {\n\t\tt.Errorf(\"expected result to be != nil; got: %v\", indexResult)\n\t}\n\n\tquery := NewTermQuery(\"user\", \"olivere\")\n\texplain := true\n\tvalid, err := client.Validate(testIndexName).Explain(&explain).Query(query).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif valid == nil {\n\t\tt.Fatal(\"expected to return an validation\")\n\t}\n\tif !valid.Valid {\n\t\tt.Errorf(\"expected valid to be %v; got: %v\", true, valid.Valid)\n\t}\n\n\tinvalidQuery := NewTermQuery(\"\", false)\n\tvalid, err = client.Validate(testIndexName).Query(invalidQuery).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif valid == nil {\n\t\tt.Fatal(\"expected to return an validation\")\n\t}\n\tif valid.Valid {\n\t\tt.Errorf(\"expected valid to be %v; got: %v\", false, valid.Valid)\n\t}\n}\n"
  },
  {
    "path": "xpack_async_search_delete.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// XPackAsyncSearchDelete allows removing an asynchronous search result,\n// previously being started with XPackAsyncSearchSubmit service.\n//\n// For more details, see the documentation at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.9/async-search.html\ntype XPackAsyncSearchDelete struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\t// ID of asynchronous search as returned by XPackAsyncSearchSubmit.Do.\n\tid string\n}\n\n// NewXPackAsyncSearchDelete creates a new XPackAsyncSearchDelete.\nfunc NewXPackAsyncSearchDelete(client *Client) *XPackAsyncSearchDelete {\n\treturn &XPackAsyncSearchDelete{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackAsyncSearchDelete) Pretty(pretty bool) *XPackAsyncSearchDelete {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackAsyncSearchDelete) Human(human bool) *XPackAsyncSearchDelete {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackAsyncSearchDelete) ErrorTrace(errorTrace bool) *XPackAsyncSearchDelete {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackAsyncSearchDelete) FilterPath(filterPath ...string) *XPackAsyncSearchDelete {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackAsyncSearchDelete) Header(name string, value string) *XPackAsyncSearchDelete {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackAsyncSearchDelete) Headers(headers http.Header) *XPackAsyncSearchDelete {\n\ts.headers = headers\n\treturn s\n}\n\n// ID of the asynchronous search.\nfunc (s *XPackAsyncSearchDelete) ID(id string) *XPackAsyncSearchDelete {\n\ts.id = id\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackAsyncSearchDelete) buildURL() (string, url.Values, error) {\n\tpath := fmt.Sprintf(\"/_async_search/%s\", url.PathEscape(s.id))\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackAsyncSearchDelete) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"ID\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackAsyncSearchDelete) Do(ctx context.Context) (*XPackAsyncSearchDeleteResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackAsyncSearchDeleteResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackAsyncSearchDeleteResponse is the outcome of calling XPackAsyncSearchDelete.Do.\ntype XPackAsyncSearchDeleteResponse struct {\n\tAcknowledged bool `json:\"acknowledged\"`\n}\n"
  },
  {
    "path": "xpack_async_search_get.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// XPackAsyncSearchGet allows retrieving an asynchronous search result,\n// previously being started with XPackAsyncSearchSubmit service.\n//\n// For more details, see the documentation at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.9/async-search.html\ntype XPackAsyncSearchGet struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\t// ID of asynchronous search as returned by XPackAsyncSearchSubmit.Do.\n\tid string\n\t// waitForCompletionTimeout is the duration the call should wait for a result\n\t// before timing out. The default is 1 second.\n\twaitForCompletionTimeout string\n\t// keepAlive asks Elasticsearch to keep the ID and its results even\n\t// after the search has been completed.\n\tkeepAlive string\n}\n\n// NewXPackAsyncSearchGet creates a new XPackAsyncSearchGet.\nfunc NewXPackAsyncSearchGet(client *Client) *XPackAsyncSearchGet {\n\treturn &XPackAsyncSearchGet{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackAsyncSearchGet) Pretty(pretty bool) *XPackAsyncSearchGet {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackAsyncSearchGet) Human(human bool) *XPackAsyncSearchGet {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackAsyncSearchGet) ErrorTrace(errorTrace bool) *XPackAsyncSearchGet {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackAsyncSearchGet) FilterPath(filterPath ...string) *XPackAsyncSearchGet {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackAsyncSearchGet) Header(name string, value string) *XPackAsyncSearchGet {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackAsyncSearchGet) Headers(headers http.Header) *XPackAsyncSearchGet {\n\ts.headers = headers\n\treturn s\n}\n\n// ID of the asynchronous search.\nfunc (s *XPackAsyncSearchGet) ID(id string) *XPackAsyncSearchGet {\n\ts.id = id\n\treturn s\n}\n\n// WaitForCompletionTimeout specifies the time the service waits for retrieving\n// a complete result. If the timeout expires, you'll get the current results which\n// might not be complete.\nfunc (s *XPackAsyncSearchGet) WaitForCompletionTimeout(waitForCompletionTimeout string) *XPackAsyncSearchGet {\n\ts.waitForCompletionTimeout = waitForCompletionTimeout\n\treturn s\n}\n\n// KeepAlive is the time the search results are kept by Elasticsearch before\n// being garbage collected.\nfunc (s *XPackAsyncSearchGet) KeepAlive(keepAlive string) *XPackAsyncSearchGet {\n\ts.keepAlive = keepAlive\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackAsyncSearchGet) buildURL() (string, url.Values, error) {\n\tpath := fmt.Sprintf(\"/_async_search/%s\", url.PathEscape(s.id))\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.waitForCompletionTimeout != \"\" {\n\t\tparams.Set(\"wait_for_completion_timeout\", s.waitForCompletionTimeout)\n\t}\n\tif s.keepAlive != \"\" {\n\t\tparams.Set(\"keep_alive\", s.keepAlive)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackAsyncSearchGet) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"ID\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackAsyncSearchGet) Do(ctx context.Context) (*XPackAsyncSearchResult, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackAsyncSearchResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\tret.Header = res.Header\n\t\treturn nil, err\n\t}\n\tret.Header = res.Header\n\treturn ret, nil\n}\n"
  },
  {
    "path": "xpack_async_search_submit.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackAsyncSearchSubmit is an XPack API for asynchronously\n// searching for documents in Elasticsearch.\n//\n// For more details, see the documentation at\n// https://www.elastic.co/guide/en/elasticsearch/reference/7.9/async-search.html\ntype XPackAsyncSearchSubmit struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tsearchSource               *SearchSource // q\n\tsource                     interface{}\n\tsearchType                 string // search_type\n\tindex                      []string\n\ttyp                        []string\n\trouting                    string // routing\n\tpreference                 string // preference\n\trequestCache               *bool  // request_cache\n\tignoreUnavailable          *bool  // ignore_unavailable\n\tignoreThrottled            *bool  // ignore_throttled\n\tallowNoIndices             *bool  // allow_no_indices\n\texpandWildcards            string // expand_wildcards\n\tlenient                    *bool  // lenient\n\tmaxResponseSize            int64\n\tallowPartialSearchResults  *bool // allow_partial_search_results\n\ttypedKeys                  *bool // typed_keys\n\tseqNoPrimaryTerm           *bool // seq_no_primary_term\n\tbatchedReduceSize          *int  // batched_reduce_size\n\tmaxConcurrentShardRequests *int  // max_concurrent_shard_requests\n\tpreFilterShardSize         *int  // pre_filter_shard_size\n\trestTotalHitsAsInt         *bool // rest_total_hits_as_int\n\n\tccsMinimizeRoundtrips *bool // ccs_minimize_roundtrips\n\n\twaitForCompletionTimeout string // e.g. \"1s\"\n\tkeepOnCompletion         *bool\n\tkeepAlive                string // e.g. \"1h\"\n}\n\n// NewXPackAsyncSearchSubmit creates a new service for asynchronously\n// searching in Elasticsearch.\nfunc NewXPackAsyncSearchSubmit(client *Client) *XPackAsyncSearchSubmit {\n\tbuilder := &XPackAsyncSearchSubmit{\n\t\tclient:       client,\n\t\tsearchSource: NewSearchSource(),\n\t}\n\treturn builder\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackAsyncSearchSubmit) Pretty(pretty bool) *XPackAsyncSearchSubmit {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackAsyncSearchSubmit) Human(human bool) *XPackAsyncSearchSubmit {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackAsyncSearchSubmit) ErrorTrace(errorTrace bool) *XPackAsyncSearchSubmit {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackAsyncSearchSubmit) FilterPath(filterPath ...string) *XPackAsyncSearchSubmit {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackAsyncSearchSubmit) Header(name string, value string) *XPackAsyncSearchSubmit {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackAsyncSearchSubmit) Headers(headers http.Header) *XPackAsyncSearchSubmit {\n\ts.headers = headers\n\treturn s\n}\n\n// SearchSource sets the search source builder to use with this service.\nfunc (s *XPackAsyncSearchSubmit) SearchSource(searchSource *SearchSource) *XPackAsyncSearchSubmit {\n\ts.searchSource = searchSource\n\tif s.searchSource == nil {\n\t\ts.searchSource = NewSearchSource()\n\t}\n\treturn s\n}\n\n// Source allows the user to set the request body manually without using\n// any of the structs and interfaces in Elastic.\nfunc (s *XPackAsyncSearchSubmit) Source(source interface{}) *XPackAsyncSearchSubmit {\n\ts.source = source\n\treturn s\n}\n\n// Index sets the names of the indices to use for search.\nfunc (s *XPackAsyncSearchSubmit) Index(index ...string) *XPackAsyncSearchSubmit {\n\ts.index = append(s.index, index...)\n\treturn s\n}\n\n// Type adds search restrictions for a list of types.\n//\n// Deprecated: Types are in the process of being removed. Instead of using a type, prefer to\n// filter on a field on the document.\nfunc (s *XPackAsyncSearchSubmit) Type(typ ...string) *XPackAsyncSearchSubmit {\n\ts.typ = append(s.typ, typ...)\n\treturn s\n}\n\n// Timeout sets the timeout to use, e.g. \"1s\" or \"1000ms\".\nfunc (s *XPackAsyncSearchSubmit) Timeout(timeout string) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Timeout(timeout)\n\treturn s\n}\n\n// Profile sets the Profile API flag on the search source.\n// When enabled, a search executed by this service will return query\n// profiling data.\nfunc (s *XPackAsyncSearchSubmit) Profile(profile bool) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Profile(profile)\n\treturn s\n}\n\n// Collapse adds field collapsing.\nfunc (s *XPackAsyncSearchSubmit) Collapse(collapse *CollapseBuilder) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Collapse(collapse)\n\treturn s\n}\n\n// TimeoutInMillis sets the timeout in milliseconds.\nfunc (s *XPackAsyncSearchSubmit) TimeoutInMillis(timeoutInMillis int) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.TimeoutInMillis(timeoutInMillis)\n\treturn s\n}\n\n// TerminateAfter specifies the maximum number of documents to collect for\n// each shard, upon reaching which the query execution will terminate early.\nfunc (s *XPackAsyncSearchSubmit) TerminateAfter(terminateAfter int) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.TerminateAfter(terminateAfter)\n\treturn s\n}\n\n// SearchType sets the search operation type. Valid values are:\n// \"dfs_query_then_fetch\" and \"query_then_fetch\".\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-search-type.html\n// for details.\nfunc (s *XPackAsyncSearchSubmit) SearchType(searchType string) *XPackAsyncSearchSubmit {\n\ts.searchType = searchType\n\treturn s\n}\n\n// Routing is a list of specific routing values to control the shards\n// the search will be executed on.\nfunc (s *XPackAsyncSearchSubmit) Routing(routings ...string) *XPackAsyncSearchSubmit {\n\ts.routing = strings.Join(routings, \",\")\n\treturn s\n}\n\n// Preference sets the preference to execute the search. Defaults to\n// randomize across shards (\"random\"). Can be set to \"_local\" to prefer\n// local shards, \"_primary\" to execute on primary shards only,\n// or a custom value which guarantees that the same order will be used\n// across different requests.\nfunc (s *XPackAsyncSearchSubmit) Preference(preference string) *XPackAsyncSearchSubmit {\n\ts.preference = preference\n\treturn s\n}\n\n// RequestCache indicates whether the cache should be used for this\n// request or not, defaults to index level setting.\nfunc (s *XPackAsyncSearchSubmit) RequestCache(requestCache bool) *XPackAsyncSearchSubmit {\n\ts.requestCache = &requestCache\n\treturn s\n}\n\n// Query sets the query to perform, e.g. MatchAllQuery.\nfunc (s *XPackAsyncSearchSubmit) Query(query Query) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Query(query)\n\treturn s\n}\n\n// PostFilter will be executed after the query has been executed and\n// only affects the search hits, not the aggregations.\n// This filter is always executed as the last filtering mechanism.\nfunc (s *XPackAsyncSearchSubmit) PostFilter(postFilter Query) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.PostFilter(postFilter)\n\treturn s\n}\n\n// FetchSource indicates whether the response should contain the stored\n// _source for every hit.\nfunc (s *XPackAsyncSearchSubmit) FetchSource(fetchSource bool) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.FetchSource(fetchSource)\n\treturn s\n}\n\n// FetchSourceContext indicates how the _source should be fetched.\nfunc (s *XPackAsyncSearchSubmit) FetchSourceContext(fetchSourceContext *FetchSourceContext) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.FetchSourceContext(fetchSourceContext)\n\treturn s\n}\n\n// Highlight adds highlighting to the search.\nfunc (s *XPackAsyncSearchSubmit) Highlight(highlight *Highlight) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Highlight(highlight)\n\treturn s\n}\n\n// GlobalSuggestText defines the global text to use with all suggesters.\n// This avoids repetition.\nfunc (s *XPackAsyncSearchSubmit) GlobalSuggestText(globalText string) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.GlobalSuggestText(globalText)\n\treturn s\n}\n\n// Suggester adds a suggester to the search.\nfunc (s *XPackAsyncSearchSubmit) Suggester(suggester Suggester) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Suggester(suggester)\n\treturn s\n}\n\n// Aggregation adds an aggreation to perform as part of the search.\nfunc (s *XPackAsyncSearchSubmit) Aggregation(name string, aggregation Aggregation) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Aggregation(name, aggregation)\n\treturn s\n}\n\n// MinScore sets the minimum score below which docs will be filtered out.\nfunc (s *XPackAsyncSearchSubmit) MinScore(minScore float64) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.MinScore(minScore)\n\treturn s\n}\n\n// From index to start the search from. Defaults to 0.\nfunc (s *XPackAsyncSearchSubmit) From(from int) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.From(from)\n\treturn s\n}\n\n// Size is the number of search hits to return. Defaults to 10.\nfunc (s *XPackAsyncSearchSubmit) Size(size int) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Size(size)\n\treturn s\n}\n\n// Explain indicates whether each search hit should be returned with\n// an explanation of the hit (ranking).\nfunc (s *XPackAsyncSearchSubmit) Explain(explain bool) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Explain(explain)\n\treturn s\n}\n\n// Version indicates whether each search hit should be returned with\n// a version associated to it.\nfunc (s *XPackAsyncSearchSubmit) Version(version bool) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Version(version)\n\treturn s\n}\n\n// Sort adds a sort order.\nfunc (s *XPackAsyncSearchSubmit) Sort(field string, ascending bool) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Sort(field, ascending)\n\treturn s\n}\n\n// SortWithInfo adds a sort order.\nfunc (s *XPackAsyncSearchSubmit) SortWithInfo(info SortInfo) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.SortWithInfo(info)\n\treturn s\n}\n\n// SortBy adds a sort order.\nfunc (s *XPackAsyncSearchSubmit) SortBy(sorter ...Sorter) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.SortBy(sorter...)\n\treturn s\n}\n\n// DocvalueField adds a single field to load from the field data cache\n// and return as part of the search.\nfunc (s *XPackAsyncSearchSubmit) DocvalueField(docvalueField string) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.DocvalueField(docvalueField)\n\treturn s\n}\n\n// DocvalueFieldWithFormat adds a single field to load from the field data cache\n// and return as part of the search.\nfunc (s *XPackAsyncSearchSubmit) DocvalueFieldWithFormat(docvalueField DocvalueField) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.DocvalueFieldWithFormat(docvalueField)\n\treturn s\n}\n\n// DocvalueFields adds one or more fields to load from the field data cache\n// and return as part of the search.\nfunc (s *XPackAsyncSearchSubmit) DocvalueFields(docvalueFields ...string) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.DocvalueFields(docvalueFields...)\n\treturn s\n}\n\n// DocvalueFieldsWithFormat adds one or more fields to load from the field data cache\n// and return as part of the search.\nfunc (s *XPackAsyncSearchSubmit) DocvalueFieldsWithFormat(docvalueFields ...DocvalueField) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.DocvalueFieldsWithFormat(docvalueFields...)\n\treturn s\n}\n\n// NoStoredFields indicates that no stored fields should be loaded, resulting in only\n// id and type to be returned per field.\nfunc (s *XPackAsyncSearchSubmit) NoStoredFields() *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.NoStoredFields()\n\treturn s\n}\n\n// StoredField adds a single field to load and return (note, must be stored) as\n// part of the search request. If none are specified, the source of the\n// document will be returned.\nfunc (s *XPackAsyncSearchSubmit) StoredField(fieldName string) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.StoredField(fieldName)\n\treturn s\n}\n\n// StoredFields\tsets the fields to load and return as part of the search request.\n// If none are specified, the source of the document will be returned.\nfunc (s *XPackAsyncSearchSubmit) StoredFields(fields ...string) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.StoredFields(fields...)\n\treturn s\n}\n\n// TrackScores is applied when sorting and controls if scores will be\n// tracked as well. Defaults to false.\nfunc (s *XPackAsyncSearchSubmit) TrackScores(trackScores bool) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.TrackScores(trackScores)\n\treturn s\n}\n\n// TrackTotalHits controls if the total hit count for the query should be tracked.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.1/search-request-track-total-hits.html\n// for details.\nfunc (s *XPackAsyncSearchSubmit) TrackTotalHits(trackTotalHits interface{}) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.TrackTotalHits(trackTotalHits)\n\treturn s\n}\n\n// SearchAfter allows a different form of pagination by using a live cursor,\n// using the results of the previous page to help the retrieval of the next.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-search-after.html\nfunc (s *XPackAsyncSearchSubmit) SearchAfter(sortValues ...interface{}) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.SearchAfter(sortValues...)\n\treturn s\n}\n\n// DefaultRescoreWindowSize sets the rescore window size for rescores\n// that don't specify their window.\nfunc (s *XPackAsyncSearchSubmit) DefaultRescoreWindowSize(defaultRescoreWindowSize int) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.DefaultRescoreWindowSize(defaultRescoreWindowSize)\n\treturn s\n}\n\n// Rescorer adds a rescorer to the search.\nfunc (s *XPackAsyncSearchSubmit) Rescorer(rescore *Rescore) *XPackAsyncSearchSubmit {\n\ts.searchSource = s.searchSource.Rescorer(rescore)\n\treturn s\n}\n\n// IgnoreUnavailable indicates whether the specified concrete indices\n// should be ignored when unavailable (missing or closed).\nfunc (s *XPackAsyncSearchSubmit) IgnoreUnavailable(ignoreUnavailable bool) *XPackAsyncSearchSubmit {\n\ts.ignoreUnavailable = &ignoreUnavailable\n\treturn s\n}\n\n// IgnoreThrottled indicates whether specified concrete, expanded or aliased\n// indices should be ignored when throttled.\nfunc (s *XPackAsyncSearchSubmit) IgnoreThrottled(ignoreThrottled bool) *XPackAsyncSearchSubmit {\n\ts.ignoreThrottled = &ignoreThrottled\n\treturn s\n}\n\n// AllowNoIndices indicates whether to ignore if a wildcard indices\n// expression resolves into no concrete indices. (This includes `_all` string\n// or when no indices have been specified).\nfunc (s *XPackAsyncSearchSubmit) AllowNoIndices(allowNoIndices bool) *XPackAsyncSearchSubmit {\n\ts.allowNoIndices = &allowNoIndices\n\treturn s\n}\n\n// ExpandWildcards indicates whether to expand wildcard expression to\n// concrete indices that are open, closed or both.\nfunc (s *XPackAsyncSearchSubmit) ExpandWildcards(expandWildcards string) *XPackAsyncSearchSubmit {\n\ts.expandWildcards = expandWildcards\n\treturn s\n}\n\n// Lenient specifies whether format-based query failures (such as providing\n// text to a numeric field) should be ignored.\nfunc (s *XPackAsyncSearchSubmit) Lenient(lenient bool) *XPackAsyncSearchSubmit {\n\ts.lenient = &lenient\n\treturn s\n}\n\n// MaxResponseSize sets an upper limit on the response body size that we accept,\n// to guard against OOM situations.\nfunc (s *XPackAsyncSearchSubmit) MaxResponseSize(maxResponseSize int64) *XPackAsyncSearchSubmit {\n\ts.maxResponseSize = maxResponseSize\n\treturn s\n}\n\n// AllowPartialSearchResults indicates if an error should be returned if\n// there is a partial search failure or timeout.\nfunc (s *XPackAsyncSearchSubmit) AllowPartialSearchResults(enabled bool) *XPackAsyncSearchSubmit {\n\ts.allowPartialSearchResults = &enabled\n\treturn s\n}\n\n// TypedKeys specifies whether aggregation and suggester names should be\n// prefixed by their respective types in the response.\nfunc (s *XPackAsyncSearchSubmit) TypedKeys(enabled bool) *XPackAsyncSearchSubmit {\n\ts.typedKeys = &enabled\n\treturn s\n}\n\n// SeqNoPrimaryTerm is an alias for SeqNoAndPrimaryTerm.\n//\n// Deprecated: Use SeqNoAndPrimaryTerm instead.\nfunc (s *XPackAsyncSearchSubmit) SeqNoPrimaryTerm(enabled bool) *XPackAsyncSearchSubmit {\n\treturn s.SeqNoAndPrimaryTerm(enabled)\n}\n\n// SeqNoAndPrimaryTerm specifies whether to return sequence number and\n// primary term of the last modification of each hit.\nfunc (s *XPackAsyncSearchSubmit) SeqNoAndPrimaryTerm(enabled bool) *XPackAsyncSearchSubmit {\n\ts.seqNoPrimaryTerm = &enabled\n\treturn s\n}\n\n// BatchedReduceSize specifies the number of shard results that should be reduced\n// at once on the coordinating node. This value should be used as a protection\n// mechanism to reduce the memory overhead per search request if the potential\n// number of shards in the request can be large.\nfunc (s *XPackAsyncSearchSubmit) BatchedReduceSize(size int) *XPackAsyncSearchSubmit {\n\ts.batchedReduceSize = &size\n\treturn s\n}\n\n// MaxConcurrentShardRequests specifies the number of concurrent shard requests\n// this search executes concurrently. This value should be used to limit the\n// impact of the search on the cluster in order to limit the number of\n// concurrent shard requests.\nfunc (s *XPackAsyncSearchSubmit) MaxConcurrentShardRequests(max int) *XPackAsyncSearchSubmit {\n\ts.maxConcurrentShardRequests = &max\n\treturn s\n}\n\n// PreFilterShardSize specifies a threshold that enforces a pre-filter roundtrip\n// to prefilter search shards based on query rewriting if the number of shards\n// the search request expands to exceeds the threshold. This filter roundtrip\n// can limit the number of shards significantly if for instance a shard can\n// not match any documents based on it's rewrite method i.e. if date filters are\n// mandatory to match but the shard bounds and the query are disjoint.\nfunc (s *XPackAsyncSearchSubmit) PreFilterShardSize(threshold int) *XPackAsyncSearchSubmit {\n\ts.preFilterShardSize = &threshold\n\treturn s\n}\n\n// RestTotalHitsAsInt indicates whether hits.total should be rendered as an\n// integer or an object in the rest search response.\nfunc (s *XPackAsyncSearchSubmit) RestTotalHitsAsInt(enabled bool) *XPackAsyncSearchSubmit {\n\ts.restTotalHitsAsInt = &enabled\n\treturn s\n}\n\n// CCSMinimizeRoundtrips indicates whether network round-trips should be minimized\n// as part of cross-cluster search requests execution.\nfunc (s *XPackAsyncSearchSubmit) CCSMinimizeRoundtrips(enabled bool) *XPackAsyncSearchSubmit {\n\ts.ccsMinimizeRoundtrips = &enabled\n\treturn s\n}\n\n// WaitForCompletionTimeout is suitable for DoAsync only. It specifies the\n// timeout for the Search to wait for completion before returning an ID to\n// return the results asynchronously. In other words: If the search takes\n// longer than this value (default is 1 second), then you need to call\n// GetAsync to retrieve its final results.\nfunc (s *XPackAsyncSearchSubmit) WaitForCompletionTimeout(timeout string) *XPackAsyncSearchSubmit {\n\ts.waitForCompletionTimeout = timeout\n\treturn s\n}\n\n// KeepOnCompletion is suitable for DoAsync only. It indicates whether the\n// asynchronous search ID and its results should be kept even after the\n// search (and its results) are completed and retrieved.\nfunc (s *XPackAsyncSearchSubmit) KeepOnCompletion(keepOnCompletion bool) *XPackAsyncSearchSubmit {\n\ts.keepOnCompletion = &keepOnCompletion\n\treturn s\n}\n\n// KeepAlive can only be used with DoAsync. If set, KeepAlive specifies the\n// duration after which search ID and its results are removed from the\n// Elasticsearch cluster and hence can no longer be retrieved with GetAsync.\nfunc (s *XPackAsyncSearchSubmit) KeepAlive(keepAlive string) *XPackAsyncSearchSubmit {\n\ts.keepAlive = keepAlive\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackAsyncSearchSubmit) buildURL() (string, url.Values, error) {\n\tvar err error\n\tvar path string\n\n\tif len(s.index) > 0 && len(s.typ) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/{type}/_async_search\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t\t\"type\":  strings.Join(s.typ, \",\"),\n\t\t})\n\t} else if len(s.index) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/{index}/_async_search\", map[string]string{\n\t\t\t\"index\": strings.Join(s.index, \",\"),\n\t\t})\n\t} else if len(s.typ) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_all/{type}/_async_search\", map[string]string{\n\t\t\t\"type\": strings.Join(s.typ, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_async_search\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.searchType != \"\" {\n\t\tparams.Set(\"search_type\", s.searchType)\n\t}\n\tif s.routing != \"\" {\n\t\tparams.Set(\"routing\", s.routing)\n\t}\n\tif s.preference != \"\" {\n\t\tparams.Set(\"preference\", s.preference)\n\t}\n\tif v := s.requestCache; v != nil {\n\t\tparams.Set(\"request_cache\", fmt.Sprint(*v))\n\t}\n\tif v := s.allowNoIndices; v != nil {\n\t\tparams.Set(\"allow_no_indices\", fmt.Sprint(*v))\n\t}\n\tif s.expandWildcards != \"\" {\n\t\tparams.Set(\"expand_wildcards\", s.expandWildcards)\n\t}\n\tif v := s.lenient; v != nil {\n\t\tparams.Set(\"lenient\", fmt.Sprint(*v))\n\t}\n\tif v := s.ignoreUnavailable; v != nil {\n\t\tparams.Set(\"ignore_unavailable\", fmt.Sprint(*v))\n\t}\n\tif v := s.ignoreThrottled; v != nil {\n\t\tparams.Set(\"ignore_throttled\", fmt.Sprint(*v))\n\t}\n\tif s.seqNoPrimaryTerm != nil {\n\t\tparams.Set(\"seq_no_primary_term\", fmt.Sprint(*s.seqNoPrimaryTerm))\n\t}\n\tif v := s.allowPartialSearchResults; v != nil {\n\t\tparams.Set(\"allow_partial_search_results\", fmt.Sprint(*v))\n\t}\n\tif v := s.typedKeys; v != nil {\n\t\tparams.Set(\"typed_keys\", fmt.Sprint(*v))\n\t}\n\tif v := s.batchedReduceSize; v != nil {\n\t\tparams.Set(\"batched_reduce_size\", fmt.Sprint(*v))\n\t}\n\tif v := s.maxConcurrentShardRequests; v != nil {\n\t\tparams.Set(\"max_concurrent_shard_requests\", fmt.Sprint(*v))\n\t}\n\tif v := s.preFilterShardSize; v != nil {\n\t\tparams.Set(\"pre_filter_shard_size\", fmt.Sprint(*v))\n\t}\n\tif v := s.restTotalHitsAsInt; v != nil {\n\t\tparams.Set(\"rest_total_hits_as_int\", fmt.Sprint(*v))\n\t}\n\tif v := s.ccsMinimizeRoundtrips; v != nil {\n\t\tparams.Set(\"ccs_minimize_roundtrips\", fmt.Sprint(*v))\n\t}\n\tif s.waitForCompletionTimeout != \"\" {\n\t\tparams.Set(\"wait_for_completion_timeout\", s.waitForCompletionTimeout)\n\t}\n\tif v := s.keepOnCompletion; v != nil {\n\t\tparams.Set(\"keep_on_completion\", fmt.Sprint(*v))\n\t}\n\tif s.keepAlive != \"\" {\n\t\tparams.Set(\"keep_alive\", s.keepAlive)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackAsyncSearchSubmit) Validate() error {\n\treturn nil\n}\n\n// Do executes the search and returns a XPackAsyncSearchResult.\nfunc (s *XPackAsyncSearchSubmit) Do(ctx context.Context) (*XPackAsyncSearchResult, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Perform request\n\tvar body interface{}\n\tif s.source != nil {\n\t\tbody = s.source\n\t} else {\n\t\tsrc, err := s.searchSource.Source()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbody = src\n\t}\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:          \"POST\",\n\t\tPath:            path,\n\t\tParams:          params,\n\t\tBody:            body,\n\t\tHeaders:         s.headers,\n\t\tMaxResponseSize: s.maxResponseSize,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return search results\n\tret := new(XPackAsyncSearchResult)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\tret.Header = res.Header\n\t\treturn nil, err\n\t}\n\tret.Header = res.Header\n\treturn ret, nil\n}\n\n// XPackAsyncSearchResult is the outcome of starting an asynchronous search\n// or retrieving a search result with XPackAsyncSearchGet.\ntype XPackAsyncSearchResult struct {\n\tHeader               http.Header   `json:\"-\"`\n\tID                   string        `json:\"id,omitempty\"`\n\tIsRunning            bool          `json:\"is_running\"`\n\tIsPartial            bool          `json:\"is_partial\"`\n\tStartTimeMillis      int64         `json:\"start_time_in_millis,omitempty\"`\n\tExpirationTimeMillis int64         `json:\"expiration_time_in_millis,omitempty\"`\n\tResponse             *SearchResult `json:\"response,omitempty\"`\n\tError                *ErrorDetails `json:\"error,omitempty\"`\n}\n\n// Each is a utility function to iterate over all hits. It saves you from\n// checking for nil values. Notice that Each will ignore errors in\n// serializing JSON and hits with empty/nil _source will get an empty\n// value\nfunc (r *XPackAsyncSearchResult) Each(typ reflect.Type) []interface{} {\n\tif r == nil || r.Response == nil || r.Response.Hits == nil || r.Response.Hits.Hits == nil || len(r.Response.Hits.Hits) == 0 {\n\t\treturn nil\n\t}\n\tvar slice []interface{}\n\tfor _, hit := range r.Response.Hits.Hits {\n\t\tv := reflect.New(typ).Elem()\n\t\tif hit.Source == nil {\n\t\t\tslice = append(slice, v.Interface())\n\t\t\tcontinue\n\t\t}\n\t\tif err := json.Unmarshal(hit.Source, v.Addr().Interface()); err == nil {\n\t\t\tslice = append(slice, v.Interface())\n\t\t}\n\t}\n\treturn slice\n}\n"
  },
  {
    "path": "xpack_async_search_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nfunc TestXPackAsyncSearchLifecycle(t *testing.T) {\n\t//client := setupTestClientAndCreateIndexAndAddDocs(t, SetURL(\"http://elastic:elastic@localhost:9210\"), SetTraceLog(log.New(os.Stdout, \"\", log.LstdFlags)))\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\t// Match all should return all documents\n\tresp, err := client.XPackAsyncSearchSubmit().\n\t\tIndex(testIndexName).\n\t\tQuery(NewMatchAllQuery()).\n\t\tSize(100).\n\t\tPretty(true).\n\t\tWaitForCompletionTimeout(\"10s\"). // should be ready by then\n\t\tKeepOnCompletion(true).          // keep even after completion\n\t\tKeepAlive(\"2m\").                 // keep for at least 2 minutes\n\t\tDo(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif resp == nil {\n\t\tt.Fatal(\"expected response, got nil\")\n\t}\n\tif want, have := false, resp.IsRunning; want != have {\n\t\tt.Errorf(\"expected IsRunning=%v; got %v\", want, have)\n\t}\n\tif want, have := false, resp.IsPartial; want != have {\n\t\tt.Errorf(\"expected IsPartial=%v; got %v\", want, have)\n\t}\n\tif resp.ID == \"\" {\n\t\tt.Error(`expected ID!=\"\"`)\n\t}\n\tif resp.Response == nil {\n\t\tt.Fatal(\"expected Response; got nil\")\n\t}\n\tif want, have := int64(3), resp.Response.TotalHits(); want != have {\n\t\tt.Errorf(\"expected TotalHits=%v; got %v\", want, have)\n\t}\n\tfor _, hit := range resp.Response.Hits.Hits {\n\t\tif hit.Index != testIndexName {\n\t\t\tt.Errorf(\"expected SearchResult.Hits.Hit.Index = %q; got %q\", testIndexName, hit.Index)\n\t\t}\n\t\titem := make(map[string]interface{})\n\t\terr := json.Unmarshal(hit.Source, &item)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t}\n\n\t// Get the search results with the given ID\n\tget, err := client.XPackAsyncSearchGet().ID(resp.ID).Pretty(true).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif get == nil {\n\t\tt.Fatal(\"expected response, got nil\")\n\t}\n\tif want, have := false, get.IsRunning; want != have {\n\t\tt.Errorf(\"expected IsRunning=%v; got %v\", want, have)\n\t}\n\tif want, have := false, get.IsPartial; want != have {\n\t\tt.Errorf(\"expected IsPartial=%v; got %v\", want, have)\n\t}\n\tif want, have := get.ID, get.ID; want != have {\n\t\tt.Errorf(\"expected ID!=%q; got %q\", want, have)\n\t}\n\tif get.Response == nil {\n\t\tt.Fatal(\"expected Response; got nil\")\n\t}\n\tif want, have := int64(3), get.Response.TotalHits(); want != have {\n\t\tt.Errorf(\"expected TotalHits=%v; got %v\", want, have)\n\t}\n\n\t// Delete the search results with the given ID\n\tdel, err := client.XPackAsyncSearchDelete().ID(resp.ID).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif del == nil {\n\t\tt.Fatal(\"expected response, got nil\")\n\t}\n\tif want, have := true, del.Acknowledged; want != have {\n\t\tt.Errorf(\"expected Acknowledged=%v; got %v\", want, have)\n\t}\n}\n"
  },
  {
    "path": "xpack_ilm_delete_lifecycle.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// See the documentation at\n// https://www.elastic.co/guide/en/elasticsearch/reference/6.7/ilm-get-lifecycle.html.\ntype XPackIlmDeleteLifecycleService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tpolicy        string\n\ttimeout       string\n\tmasterTimeout string\n\tflatSettings  *bool\n\tlocal         *bool\n}\n\n// NewXPackIlmDeleteLifecycleService creates a new XPackIlmDeleteLifecycleService.\nfunc NewXPackIlmDeleteLifecycleService(client *Client) *XPackIlmDeleteLifecycleService {\n\treturn &XPackIlmDeleteLifecycleService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackIlmDeleteLifecycleService) Pretty(pretty bool) *XPackIlmDeleteLifecycleService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackIlmDeleteLifecycleService) Human(human bool) *XPackIlmDeleteLifecycleService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackIlmDeleteLifecycleService) ErrorTrace(errorTrace bool) *XPackIlmDeleteLifecycleService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackIlmDeleteLifecycleService) FilterPath(filterPath ...string) *XPackIlmDeleteLifecycleService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackIlmDeleteLifecycleService) Header(name string, value string) *XPackIlmDeleteLifecycleService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackIlmDeleteLifecycleService) Headers(headers http.Header) *XPackIlmDeleteLifecycleService {\n\ts.headers = headers\n\treturn s\n}\n\n// Policy is the name of the index lifecycle policy.\nfunc (s *XPackIlmDeleteLifecycleService) Policy(policy string) *XPackIlmDeleteLifecycleService {\n\ts.policy = policy\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *XPackIlmDeleteLifecycleService) Timeout(timeout string) *XPackIlmDeleteLifecycleService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *XPackIlmDeleteLifecycleService) MasterTimeout(masterTimeout string) *XPackIlmDeleteLifecycleService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// FlatSettings is returns settings in flat format (default: false).\nfunc (s *XPackIlmDeleteLifecycleService) FlatSettings(flatSettings bool) *XPackIlmDeleteLifecycleService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackIlmDeleteLifecycleService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tpath, err = uritemplates.Expand(\"/_ilm/policy/{policy}\", map[string]string{\n\t\t\"policy\": s.policy,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.flatSettings; v != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprint(*v))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackIlmDeleteLifecycleService) Validate() error {\n\tvar invalid []string\n\tif s.policy == \"\" {\n\t\tinvalid = append(invalid, \"Policy\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackIlmDeleteLifecycleService) Do(ctx context.Context) (*XPackIlmDeleteLifecycleResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Delete URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Delete HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackIlmDeleteLifecycleResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackIlmDeleteLifecycleResponse is the response of XPackIlmDeleteLifecycleService.Do.\ntype XPackIlmDeleteLifecycleResponse struct {\n\tAcknowledged bool `json:\"acknowledged\"`\n}\n"
  },
  {
    "path": "xpack_ilm_get_lifecycle.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// See the documentation at\n// https://www.elastic.co/guide/en/elasticsearch/reference/6.7/ilm-get-lifecycle.html.\ntype XPackIlmGetLifecycleService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tpolicy        []string\n\ttimeout       string\n\tmasterTimeout string\n\tflatSettings  *bool\n\tlocal         *bool\n}\n\n// NewXPackIlmGetLifecycleService creates a new XPackIlmGetLifecycleService.\nfunc NewXPackIlmGetLifecycleService(client *Client) *XPackIlmGetLifecycleService {\n\treturn &XPackIlmGetLifecycleService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackIlmGetLifecycleService) Pretty(pretty bool) *XPackIlmGetLifecycleService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackIlmGetLifecycleService) Human(human bool) *XPackIlmGetLifecycleService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackIlmGetLifecycleService) ErrorTrace(errorTrace bool) *XPackIlmGetLifecycleService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackIlmGetLifecycleService) FilterPath(filterPath ...string) *XPackIlmGetLifecycleService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackIlmGetLifecycleService) Header(name string, value string) *XPackIlmGetLifecycleService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackIlmGetLifecycleService) Headers(headers http.Header) *XPackIlmGetLifecycleService {\n\ts.headers = headers\n\treturn s\n}\n\n// Policy is the name of the index lifecycle policy.\nfunc (s *XPackIlmGetLifecycleService) Policy(policies ...string) *XPackIlmGetLifecycleService {\n\ts.policy = append(s.policy, policies...)\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *XPackIlmGetLifecycleService) Timeout(timeout string) *XPackIlmGetLifecycleService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *XPackIlmGetLifecycleService) MasterTimeout(masterTimeout string) *XPackIlmGetLifecycleService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// FlatSettings is returns settings in flat format (default: false).\nfunc (s *XPackIlmGetLifecycleService) FlatSettings(flatSettings bool) *XPackIlmGetLifecycleService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackIlmGetLifecycleService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar err error\n\tvar path string\n\tif len(s.policy) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_ilm/policy/{policy}\", map[string]string{\n\t\t\t\"policy\": strings.Join(s.policy, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_ilm/policy\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.flatSettings; v != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprint(*v))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif v := s.local; v != nil {\n\t\tparams.Set(\"local\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackIlmGetLifecycleService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackIlmGetLifecycleService) Do(ctx context.Context) (map[string]*XPackIlmGetLifecycleResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tvar ret map[string]*XPackIlmGetLifecycleResponse\n\tif err := s.client.decoder.Decode(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackIlmGetLifecycleResponse is the response of XPackIlmGetLifecycleService.Do.\ntype XPackIlmGetLifecycleResponse struct {\n\tVersion      int                       `json:\"version,omitempty\"`\n\tModifiedDate string                    `json:\"modified_date,omitempty\"` // e.g. \"2019-10-03T17:43:42.720Z\"\n\tPolicy       map[string]interface{}    `json:\"policy,omitempty\"`\n\tInUseBy      *ClusterMetadataItemUsage `json:\"in_use_by,omitempty\"`\n}\n\n// ClusterMetadataItemUsage encapsulates the usage of a particular \"thing\"\n// by something else. In Elasticsearch, this is in the\n// org.elasticsearch.cluster.metadata package.\ntype ClusterMetadataItemUsage struct {\n\tIndices             []string `json:\"indices,omitempty\"`\n\tDataStreams         []string `json:\"data_streams,omitempty\"`\n\tComposableTemplates []string `json:\"composable_templates,omitempty\"`\n}\n"
  },
  {
    "path": "xpack_ilm_put_lifecycle.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// See the documentation at\n// https://www.elastic.co/guide/en/elasticsearch/reference/6.7/ilm-put-lifecycle.html\ntype XPackIlmPutLifecycleService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tpolicy        string\n\ttimeout       string\n\tmasterTimeout string\n\tflatSettings  *bool\n\tbodyJson      interface{}\n\tbodyString    string\n}\n\n// NewXPackIlmPutLifecycleService creates a new XPackIlmPutLifecycleService.\nfunc NewXPackIlmPutLifecycleService(client *Client) *XPackIlmPutLifecycleService {\n\treturn &XPackIlmPutLifecycleService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackIlmPutLifecycleService) Pretty(pretty bool) *XPackIlmPutLifecycleService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackIlmPutLifecycleService) Human(human bool) *XPackIlmPutLifecycleService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackIlmPutLifecycleService) ErrorTrace(errorTrace bool) *XPackIlmPutLifecycleService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackIlmPutLifecycleService) FilterPath(filterPath ...string) *XPackIlmPutLifecycleService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackIlmPutLifecycleService) Header(name string, value string) *XPackIlmPutLifecycleService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackIlmPutLifecycleService) Headers(headers http.Header) *XPackIlmPutLifecycleService {\n\ts.headers = headers\n\treturn s\n}\n\n// Policy is the name of the index lifecycle policy.\nfunc (s *XPackIlmPutLifecycleService) Policy(policy string) *XPackIlmPutLifecycleService {\n\ts.policy = policy\n\treturn s\n}\n\n// Timeout is an explicit operation timeout.\nfunc (s *XPackIlmPutLifecycleService) Timeout(timeout string) *XPackIlmPutLifecycleService {\n\ts.timeout = timeout\n\treturn s\n}\n\n// MasterTimeout specifies the timeout for connection to master.\nfunc (s *XPackIlmPutLifecycleService) MasterTimeout(masterTimeout string) *XPackIlmPutLifecycleService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// FlatSettings indicates whether to return settings in flat format (default: false).\nfunc (s *XPackIlmPutLifecycleService) FlatSettings(flatSettings bool) *XPackIlmPutLifecycleService {\n\ts.flatSettings = &flatSettings\n\treturn s\n}\n\n// BodyJson is documented as: The template definition.\nfunc (s *XPackIlmPutLifecycleService) BodyJson(body interface{}) *XPackIlmPutLifecycleService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is documented as: The template definition.\nfunc (s *XPackIlmPutLifecycleService) BodyString(body string) *XPackIlmPutLifecycleService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackIlmPutLifecycleService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_ilm/policy/{policy}\", map[string]string{\n\t\t\"policy\": s.policy,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.timeout != \"\" {\n\t\tparams.Set(\"timeout\", s.timeout)\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif v := s.flatSettings; v != nil {\n\t\tparams.Set(\"flat_settings\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackIlmPutLifecycleService) Validate() error {\n\tvar invalid []string\n\tif s.policy == \"\" {\n\t\tinvalid = append(invalid, \"Policy\")\n\t}\n\tif s.bodyString == \"\" && s.bodyJson == nil {\n\t\tinvalid = append(invalid, \"BodyJson\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackIlmPutLifecycleService) Do(ctx context.Context) (*XPackIlmPutLifecycleResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackIlmPutLifecycleResponse)\n\tif err := s.client.decoder.Decode(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackIlmPutLifecycleSResponse is the response of XPackIlmPutLifecycleService.Do.\ntype XPackIlmPutLifecycleResponse struct {\n\tAcknowledged bool `json:\"acknowledged\"`\n}\n"
  },
  {
    "path": "xpack_ilm_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestXPackIlmPolicyLifecycle(t *testing.T) {\n\tclient := setupTestClient(t, SetURL(\"http://elastic:elastic@localhost:9210\")) //, SetTraceLog(log.New(os.Stdout, \"\", 0)))\n\n\ttestPolicyName := \"test-policy\"\n\n\tbody := `{\n\t\t\"policy\": {\n\t\t\t\"phases\": {\n\t\t\t\t\"delete\": {\n\t\t\t\t\t\"min_age\": \"20m\",\n\t\t\t\t\t\"actions\": {\n\t\t\t\t\t\t\"delete\": {}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}`\n\n\t// Create the policy\n\tputilm, err := client.XPackIlmPutLifecycle().Policy(testPolicyName).BodyString(body).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected put lifecycle to succeed; got: %v\", err)\n\t}\n\tif putilm == nil {\n\t\tt.Fatalf(\"expected put lifecycle response; got: %v\", putilm)\n\t}\n\tif !putilm.Acknowledged {\n\t\tt.Fatalf(\"expected put lifecycle ack; got: %v\", putilm.Acknowledged)\n\t}\n\n\t// Get the policy\n\tgetilm, err := client.XPackIlmGetLifecycle().Policy(testPolicyName).Pretty(true).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected get lifecycle to succeed; got: %v\", err)\n\t}\n\tif getilm == nil {\n\t\tt.Fatalf(\"expected get lifecycle response; got: %v\", getilm)\n\t}\n\n\t// Check the policy exists\n\t_, found := getilm[testPolicyName]\n\tif !found {\n\t\tt.Fatalf(\"expected to get policy for %q\", testPolicyName)\n\t}\n\n\t// Delete the policy\n\tdelilm, err := client.XPackIlmDeleteLifecycle().Policy(testPolicyName).Do(context.TODO())\n\tif err != nil {\n\t\tt.Fatalf(\"expected deletelifecycle to succeed; got: %v\", err)\n\t}\n\tif delilm == nil {\n\t\tt.Fatalf(\"expected delete lifecycle response; got: %v\", delilm)\n\t}\n\tif !delilm.Acknowledged {\n\t\tt.Fatalf(\"expected delete lifecycle ack; got: %v\", delilm.Acknowledged)\n\t}\n\n\t// Get the policy\n\tgetilm, err = client.XPackIlmGetLifecycle().Policy(testPolicyName).Do(context.TODO())\n\tif err == nil {\n\t\tt.Fatalf(\"expected lifecycle to be deleted; got: %v\", getilm)\n\t}\n}\n"
  },
  {
    "path": "xpack_info.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackInfoService retrieves xpack info.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/info-api.html.\ntype XPackInfoService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n}\n\n// NewXPackInfoService creates a new XPackInfoService.\nfunc NewXPackInfoService(client *Client) *XPackInfoService {\n\treturn &XPackInfoService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackInfoService) Pretty(pretty bool) *XPackInfoService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackInfoService) Human(human bool) *XPackInfoService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackInfoService) ErrorTrace(errorTrace bool) *XPackInfoService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackInfoService) FilterPath(filterPath ...string) *XPackInfoService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackInfoService) Header(name string, value string) *XPackInfoService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackInfoService) Headers(headers http.Header) *XPackInfoService {\n\ts.headers = headers\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackInfoService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_xpack\", map[string]string{})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackInfoService) Validate() error {\n\tvar invalid []string\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackInfoService) Do(ctx context.Context) (*XPackInfoServiceResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := XPackInfoServiceResponse{}\n\tif err := json.Unmarshal(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &ret, nil\n}\n\n// XPackInfoServiceResponse is the response of XPackInfoService.Do.\ntype XPackInfoServiceResponse struct {\n\tBuild    XPackInfoBuild    `json:\"build\"`\n\tLicense  XPackInfoLicense  `json:\"license\"`\n\tFeatures XPackInfoFeatures `json:\"features\"`\n\tTagline  string            `json:\"tagline\"`\n}\n\n// XPackInfoBuild is the xpack build info\ntype XPackInfoBuild struct {\n\tHash string `json:\"hash\"`\n\tDate string `json:\"date\"`\n}\n\n// XPackInfoLicense is the xpack license info\ntype XPackInfoLicense struct {\n\tUID         string `json:\"uid\"`\n\tType        string `json:\"type\"`\n\tMode        string `json:\"mode\"`\n\tStatus      string `json:\"status\"`\n\tExpiryMilis int    `json:\"expiry_date_in_millis\"`\n}\n\n// XPackInfoFeatures is the xpack feature info object\ntype XPackInfoFeatures struct {\n\tGraph           XPackInfoGraph      `json:\"graph\"`\n\tLogstash        XPackInfoLogstash   `json:\"logstash\"`\n\tMachineLearning XPackInfoML         `json:\"ml\"`\n\tMonitoring      XPackInfoMonitoring `json:\"monitoring\"`\n\tRollup          XPackInfoRollup     `json:\"rollup\"`\n\tSecurity        XPackInfoSecurity   `json:\"security\"`\n\tWatcher         XPackInfoWatcher    `json:\"watcher\"`\n}\n\n// XPackInfoGraph is the xpack graph plugin info\ntype XPackInfoGraph struct {\n\tDescription string `json:\"description\"`\n\tAvailable   bool   `json:\"available\"`\n\tEnabled     bool   `json:\"enabled\"`\n}\n\n// XPackInfoLogstash is the xpack logstash plugin info\ntype XPackInfoLogstash struct {\n\tDescription string `json:\"description\"`\n\tAvailable   bool   `json:\"available\"`\n\tEnabled     bool   `json:\"enabled\"`\n}\n\n// XPackInfoML is the xpack machine learning plugin info\ntype XPackInfoML struct {\n\tDescription    string            `json:\"description\"`\n\tAvailable      bool              `json:\"available\"`\n\tEnabled        bool              `json:\"enabled\"`\n\tNativeCodeInfo map[string]string `json:\"native_code_info\"`\n}\n\n// XPackInfoMonitoring is the xpack monitoring plugin info\ntype XPackInfoMonitoring struct {\n\tDescription string `json:\"description\"`\n\tAvailable   bool   `json:\"available\"`\n\tEnabled     bool   `json:\"enabled\"`\n}\n\n// XPackInfoRollup is the xpack rollup plugin info\ntype XPackInfoRollup struct {\n\tDescription string `json:\"description\"`\n\tAvailable   bool   `json:\"available\"`\n\tEnabled     bool   `json:\"enabled\"`\n}\n\n// XPackInfoSecurity is the xpack security plugin info\ntype XPackInfoSecurity struct {\n\tDescription string `json:\"description\"`\n\tAvailable   bool   `json:\"available\"`\n\tEnabled     bool   `json:\"enabled\"`\n}\n\n// XPackInfoWatcher is the xpack watcher plugin info\ntype XPackInfoWatcher struct {\n\tDescription string `json:\"description\"`\n\tAvailable   bool   `json:\"available\"`\n\tEnabled     bool   `json:\"enabled\"`\n}\n"
  },
  {
    "path": "xpack_info_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackInfoBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"/_xpack\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackInfo()\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_rollup_delete.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackRollupDeleteService delete a rollup job by its job id.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/rollup-delete-job.html.\ntype XPackRollupDeleteService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tjobId string\n}\n\n// XPackRollupDeleteService creates a new XPackRollupDeleteService.\nfunc NewXPackRollupDeleteService(client *Client) *XPackRollupDeleteService {\n\treturn &XPackRollupDeleteService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackRollupDeleteService) Pretty(pretty bool) *XPackRollupDeleteService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackRollupDeleteService) Human(human bool) *XPackRollupDeleteService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackRollupDeleteService) ErrorTrace(errorTrace bool) *XPackRollupDeleteService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackRollupDeleteService) FilterPath(filterPath ...string) *XPackRollupDeleteService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackRollupDeleteService) Header(name string, value string) *XPackRollupDeleteService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackRollupDeleteService) Headers(headers http.Header) *XPackRollupDeleteService {\n\ts.headers = headers\n\treturn s\n}\n\n// JobId is id of the rollup to delete.\nfunc (s *XPackRollupDeleteService) JobId(jobId string) *XPackRollupDeleteService {\n\ts.jobId = jobId\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackRollupDeleteService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_rollup/job/{job_id}\", map[string]string{\n\t\t\"job_id\": s.jobId,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackRollupDeleteService) Validate() error {\n\tvar invalid []string\n\tif s.jobId == \"\" {\n\t\tinvalid = append(invalid, \"Job ID\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackRollupDeleteService) Do(ctx context.Context) (*XPackRollupDeleteResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackRollupDeleteResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackRollupDeleteResponse is the response of XPackRollupDeleteService.Do.\ntype XPackRollupDeleteResponse struct {\n\tAcknowledged bool `json:\"acknowledged\"`\n}\n"
  },
  {
    "path": "xpack_rollup_delete_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackRollupDeleteBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tJobId        string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-job\",\n\t\t\t\"/_rollup/job/my-job\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackRollupDelete(test.JobId)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_rollup_get.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackRollupGetService retrieves a role by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/rollup-apis.html.\ntype XPackRollupGetService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tjobId string\n}\n\n// NewXPackRollupGetService creates a new XPackRollupGetService.\nfunc NewXPackRollupGetService(client *Client) *XPackRollupGetService {\n\treturn &XPackRollupGetService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackRollupGetService) Pretty(pretty bool) *XPackRollupGetService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackRollupGetService) Human(human bool) *XPackRollupGetService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackRollupGetService) ErrorTrace(errorTrace bool) *XPackRollupGetService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackRollupGetService) FilterPath(filterPath ...string) *XPackRollupGetService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackRollupGetService) Header(name string, value string) *XPackRollupGetService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackRollupGetService) Headers(headers http.Header) *XPackRollupGetService {\n\ts.headers = headers\n\treturn s\n}\n\n// JobId is id of the rollup to retrieve.\nfunc (s *XPackRollupGetService) JobId(jobId string) *XPackRollupGetService {\n\ts.jobId = jobId\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackRollupGetService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_rollup/job/{job_id}\", map[string]string{\n\t\t\"job_id\": s.jobId,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackRollupGetService) Validate() error {\n\tvar invalid []string\n\tif s.jobId == \"\" {\n\t\tinvalid = append(invalid, \"Job ID\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackRollupGetService) Do(ctx context.Context) (*XPackRollupGetResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := XPackRollupGetResponse{}\n\tif err := json.Unmarshal(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &ret, nil\n}\n\n// XPackRollupGetResponse is the response of XPackRollupGetService.Do.\ntype XPackRollupGetResponse struct {\n\tJobs []XPackRollup `json:\"jobs\"`\n}\n\n// XPackRollup is the role object.\ntype XPackRollup struct {\n\tConfig XPackRollupConfig `json:\"config\"`\n\tStatus XPackRollupStatus `json:\"status\"`\n\tStats  XPackRollupStats  `json:\"stats\"`\n}\n\ntype XPackRollupConfig struct {\n\tId           string                 `json:\"id\"`\n\tCron         string                 `json:\"cron\"`\n\tIndexPattern string                 `json:\"index_pattern\"`\n\tRollupIndex  string                 `json:\"rollup_index\"`\n\tGroups       map[string]interface{} `json:\"groups\"`\n\tMetrics      []XPackRollupMetrics   `json:\"metrics\"`\n\tTimeout      string                 `json:\"timeout\"`\n\tPageSize     int                    `json:\"page_size\"`\n}\n\ntype XPackRollupMetrics struct {\n\tField   string   `json:\"field\"`\n\tMetrics []string `json:\"metrics\"`\n}\n\ntype XPackRollupStatus struct {\n\tJobState      string `json:\"job_state\"`\n\tUpgradedDocId bool   `json:\"upgraded_doc_id\"`\n}\n\ntype XPackRollupStats struct {\n\tPageProcessed      int `json:\"pages_processed\"`\n\tDocumentsProcessed int `json:\"documents_processed\"`\n\tRollupsIndexed     int `json:\"rollups_indexed\"`\n\tTriggerCount       int `json:\"trigger_count\"`\n\tIndexFailures      int `json:\"index_failures\"`\n\tIndexTimeInMs      int `json:\"index_time_in_ms\"`\n\tIndexTotal         int `json:\"index_total\"`\n\tSearchFailures     int `json:\"search_failures\"`\n\tSearchTimeInMs     int `json:\"search_time_in_ms\"`\n\tSearchTotal        int `json:\"search_total\"`\n\tProcessingTimeInMs int `json:\"processing_time_in_ms\"`\n\tProcessingTotal    int `json:\"processing_total\"`\n}\n"
  },
  {
    "path": "xpack_rollup_get_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport \"testing\"\n\nfunc TestXPackRollupGetBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tJobId        string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-job\",\n\t\t\t\"/_rollup/job/my-job\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackRollupGet(test.JobId)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_rollup_put.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackRollupPutService create or update a rollup job by its job id.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/rollup-put-job.html.\ntype XPackRollupPutService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tjobId string\n\tbody  interface{}\n}\n\n// NewXPackRollupPutService creates a new XPackRollupPutService.\nfunc NewXPackRollupPutService(client *Client) *XPackRollupPutService {\n\treturn &XPackRollupPutService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackRollupPutService) Pretty(pretty bool) *XPackRollupPutService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackRollupPutService) Human(human bool) *XPackRollupPutService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackRollupPutService) ErrorTrace(errorTrace bool) *XPackRollupPutService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackRollupPutService) FilterPath(filterPath ...string) *XPackRollupPutService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackRollupPutService) Header(name string, value string) *XPackRollupPutService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackRollupPutService) Headers(headers http.Header) *XPackRollupPutService {\n\ts.headers = headers\n\treturn s\n}\n\n// JobId is id of the rollup to create.\nfunc (s *XPackRollupPutService) JobId(jobId string) *XPackRollupPutService {\n\ts.jobId = jobId\n\treturn s\n}\n\n// Body specifies the role. Use a string or a type that will get serialized as JSON.\nfunc (s *XPackRollupPutService) Body(body interface{}) *XPackRollupPutService {\n\ts.body = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackRollupPutService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_rollup/job/{job_id}\", map[string]string{\n\t\t\"job_id\": s.jobId,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackRollupPutService) Validate() error {\n\tvar invalid []string\n\tif s.jobId == \"\" {\n\t\tinvalid = append(invalid, \"Job ID\")\n\t}\n\tif s.body == nil {\n\t\tinvalid = append(invalid, \"Body\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackRollupPutService) Do(ctx context.Context) (*XPackRollupPutResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    s.body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackRollupPutResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackRollupPutResponse is the response of XPackRollupPutService.Do.\ntype XPackRollupPutResponse struct {\n\tAcknowledged bool `json:\"acknowledged\"`\n}\n"
  },
  {
    "path": "xpack_rollup_put_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackRollupPutBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tJobId        string\n\t\tBody         interface{}\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-job\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"\",\n\t\t\t`{}`,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-job\",\n\t\t\t`{}`,\n\t\t\t\"/_rollup/job/my-job\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackRollupPut(test.JobId).Body(test.Body)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_rollup_start.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackRollupStartService starts the rollup job if it is not already running.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/rollup-start-job.html.\ntype XPackRollupStartService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tjobId string\n}\n\n// NewXPackRollupStartService creates a new XPackRollupStartService.\nfunc NewXPackRollupStartService(client *Client) *XPackRollupStartService {\n\treturn &XPackRollupStartService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackRollupStartService) Pretty(pretty bool) *XPackRollupStartService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackRollupStartService) Human(human bool) *XPackRollupStartService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackRollupStartService) ErrorTrace(errorTrace bool) *XPackRollupStartService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackRollupStartService) FilterPath(filterPath ...string) *XPackRollupStartService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackRollupStartService) Header(name string, value string) *XPackRollupStartService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackRollupStartService) Headers(headers http.Header) *XPackRollupStartService {\n\ts.headers = headers\n\treturn s\n}\n\n// JobId is id of the rollup to retrieve.\nfunc (s *XPackRollupStartService) JobId(jobId string) *XPackRollupStartService {\n\ts.jobId = jobId\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackRollupStartService) buildURL() (string, url.Values, error) {\n\t// Build URL path\n\tpath, err := uritemplates.Expand(\"/_rollup/job/{job_id}/_start\", map[string]string{\n\t\t\"job_id\": s.jobId,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackRollupStartService) Validate() error {\n\tvar invalid []string\n\tif s.jobId == \"\" {\n\t\tinvalid = append(invalid, \"Job ID\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackRollupStartService) Do(ctx context.Context) (*XPackRollupStartResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackRollupStartResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackRollupStartResponse is the response of XPackRollupStartService.Do.\ntype XPackRollupStartResponse struct {\n\tStarted bool `json:\"started\"`\n}\n"
  },
  {
    "path": "xpack_rollup_start_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackRollupStartBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"/_rollup/job/my-job/_start\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackRollupStart(\"my-job\")\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_rollup_stop.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackRollupStartService stops the rollup job if it is running.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/rollup-stop-job.html.\ntype XPackRollupStopService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tjobId string\n}\n\n// NewXPackRollupStopService creates a new XPackRollupStopService.\nfunc NewXPackRollupStopService(client *Client) *XPackRollupStopService {\n\treturn &XPackRollupStopService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackRollupStopService) Pretty(pretty bool) *XPackRollupStopService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackRollupStopService) Human(human bool) *XPackRollupStopService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackRollupStopService) ErrorTrace(errorTrace bool) *XPackRollupStopService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackRollupStopService) FilterPath(filterPath ...string) *XPackRollupStopService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackRollupStopService) Header(name string, value string) *XPackRollupStopService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackRollupStopService) Headers(headers http.Header) *XPackRollupStopService {\n\ts.headers = headers\n\treturn s\n}\n\n// JobId is id of the rollup to retrieve.\nfunc (s *XPackRollupStopService) JobId(jobId string) *XPackRollupStopService {\n\ts.jobId = jobId\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackRollupStopService) buildURL() (string, url.Values, error) {\n\t// Build URL path\n\tpath, err := uritemplates.Expand(\"/_rollup/job/{job_id}/_stop\", map[string]string{\n\t\t\"job_id\": s.jobId,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackRollupStopService) Validate() error {\n\tvar invalid []string\n\tif s.jobId == \"\" {\n\t\tinvalid = append(invalid, \"Job ID\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackRollupStopService) Do(ctx context.Context) (*XPackRollupStopResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackRollupStopResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackRollupStopResponse is the response of XPackRollupStopService.Do.\ntype XPackRollupStopResponse struct {\n\tStoppeed bool `json:\"stopped\"`\n}\n"
  },
  {
    "path": "xpack_rollup_stop_test.go",
    "content": "// Copyright 2012-present Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackRollupStopBuildURL(t *testing.T) {\n\tclient := setupTestClient(t)\n\n\ttests := []struct {\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"/_rollup/job/my-job/_stop\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackRollupStop(\"my-job\")\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_change_password.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityChangePasswordService changes a native user's password.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.1/security-api-change-password.html.\ntype XPackSecurityChangePasswordService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tusername string\n\tpassword string\n\trefresh  string\n\tbody     interface{}\n}\n\n// NewXPackSecurityChangePasswordService creates a new XPackSecurityChangePasswordService.\nfunc NewXPackSecurityChangePasswordService(client *Client) *XPackSecurityChangePasswordService {\n\treturn &XPackSecurityChangePasswordService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityChangePasswordService) Pretty(pretty bool) *XPackSecurityChangePasswordService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityChangePasswordService) Human(human bool) *XPackSecurityChangePasswordService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityChangePasswordService) ErrorTrace(errorTrace bool) *XPackSecurityChangePasswordService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityChangePasswordService) FilterPath(filterPath ...string) *XPackSecurityChangePasswordService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityChangePasswordService) Header(name string, value string) *XPackSecurityChangePasswordService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityChangePasswordService) Headers(headers http.Header) *XPackSecurityChangePasswordService {\n\ts.headers = headers\n\treturn s\n}\n\n// Username is name of the user to change.\nfunc (s *XPackSecurityChangePasswordService) Username(username string) *XPackSecurityChangePasswordService {\n\ts.username = username\n\treturn s\n}\n\n// Password is the new value of the password.\nfunc (s *XPackSecurityChangePasswordService) Password(password string) *XPackSecurityChangePasswordService {\n\ts.password = password\n\treturn s\n}\n\n// Refresh, if \"true\" (the default), refreshes the affected shards to make this operation\n// visible to search, if \"wait_for\" then wait for a refresh to make this operation visible\n// to search, if \"false\" then do nothing with refreshes.\nfunc (s *XPackSecurityChangePasswordService) Refresh(refresh string) *XPackSecurityChangePasswordService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// Body specifies the password. Use a string or a type that will get serialized as JSON.\nfunc (s *XPackSecurityChangePasswordService) Body(body interface{}) *XPackSecurityChangePasswordService {\n\ts.body = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityChangePasswordService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_xpack/security/user/{username}/_password\", map[string]string{\n\t\t\"username\": s.username,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.refresh; v != \"\" {\n\t\tparams.Set(\"refresh\", v)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityChangePasswordService) Validate() error {\n\tvar invalid []string\n\tif s.username == \"\" {\n\t\tinvalid = append(invalid, \"Userame\")\n\t}\n\tif s.password == \"\" && s.body == nil {\n\t\tinvalid = append(invalid, \"Body\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityChangePasswordService) Do(ctx context.Context) (*XPackSecurityChangeUserPasswordResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar body interface{}\n\tif s.body != nil {\n\t\tbody = s.body\n\t} else {\n\t\tbody = map[string]interface{}{\n\t\t\t\"password\": s.password,\n\t\t}\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackSecurityChangeUserPasswordResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackSecurityChangeUserPasswordResponse is the response of\n// XPackSecurityChangePasswordService.Do.\n//\n// A successful call returns an empty JSON structure: {}.\ntype XPackSecurityChangeUserPasswordResponse struct {\n}\n"
  },
  {
    "path": "xpack_security_change_password_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"net/url\"\n\t\"testing\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc TestXPackSecurityChangePasswordBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tUsername       string\n\t\tPassword       string\n\t\tRefresh        string\n\t\tBody           interface{}\n\t\tExpectedPath   string\n\t\tExpectedParams url.Values\n\t\tExpectedErr    bool\n\t}{\n\t\t// #0 No username\n\t\t{\n\t\t\tUsername:       \"\",\n\t\t\tPassword:       \"\",\n\t\t\tRefresh:        \"\",\n\t\t\tBody:           nil,\n\t\t\tExpectedPath:   \"\",\n\t\t\tExpectedParams: url.Values{},\n\t\t\tExpectedErr:    true,\n\t\t},\n\t\t// #1 No username (but body)\n\t\t{\n\t\t\tUsername:       \"\",\n\t\t\tPassword:       \"\",\n\t\t\tRefresh:        \"\",\n\t\t\tBody:           `{}`,\n\t\t\tExpectedPath:   \"\",\n\t\t\tExpectedParams: url.Values{},\n\t\t\tExpectedErr:    true,\n\t\t},\n\t\t// #2 No body or password\n\t\t{\n\t\t\tUsername:       \"my-user\",\n\t\t\tPassword:       \"\",\n\t\t\tRefresh:        \"\",\n\t\t\tBody:           nil,\n\t\t\tExpectedPath:   \"\",\n\t\t\tExpectedParams: url.Values{},\n\t\t\tExpectedErr:    true,\n\t\t},\n\t\t// #3 No password but body\n\t\t{\n\t\t\tUsername:       \"my-user\",\n\t\t\tPassword:       \"\",\n\t\t\tRefresh:        \"\",\n\t\t\tBody:           `{\"password\":\"secret\"}`,\n\t\t\tExpectedPath:   \"/_xpack/security/user/my-user/_password\",\n\t\t\tExpectedParams: url.Values{},\n\t\t\tExpectedErr:    false,\n\t\t},\n\t\t// #4 No body but password\n\t\t{\n\t\t\tUsername:       \"my-user\",\n\t\t\tPassword:       \"secret\",\n\t\t\tRefresh:        \"\",\n\t\t\tBody:           nil,\n\t\t\tExpectedPath:   \"/_xpack/security/user/my-user/_password\",\n\t\t\tExpectedParams: url.Values{},\n\t\t\tExpectedErr:    false,\n\t\t},\n\t\t// #5 With refresh option\n\t\t{\n\t\t\tUsername:     \"my-user\",\n\t\t\tPassword:     \"secret\",\n\t\t\tRefresh:      \"wait_for\",\n\t\t\tBody:         nil,\n\t\t\tExpectedPath: \"/_xpack/security/user/my-user/_password\",\n\t\t\tExpectedParams: url.Values{\n\t\t\t\t\"refresh\": []string{\"wait_for\"},\n\t\t\t},\n\t\t\tExpectedErr: false,\n\t\t},\n\t}\n\n\tfor i, tt := range tests {\n\t\tbuilder := client.XPackSecurityChangePassword(tt.Username).\n\t\t\tPassword(tt.Password).\n\t\t\tRefresh(tt.Refresh).\n\t\t\tBody(tt.Body)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !tt.ExpectedErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif tt.ExpectedErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, params, err := builder.buildURL()\n\t\t\tif err != nil {\n\t\t\t\tt.Fatalf(\"case #%d: %v\", i, err)\n\t\t\t}\n\t\t\tif path != tt.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i, tt.ExpectedPath, path)\n\t\t\t}\n\t\t\tif want, have := tt.ExpectedParams, params; !cmp.Equal(want, have) {\n\t\t\t\tt.Errorf(\"case #%d: want Params=%#v, have %#v\\n\\tdiff: %s\", i, want, have, cmp.Diff(want, have))\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_delete_role.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityDeleteRoleService delete a role by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-delete-role.html.\ntype XPackSecurityDeleteRoleService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname string\n}\n\n// NewXPackSecurityDeleteRoleService creates a new XPackSecurityDeleteRoleService.\nfunc NewXPackSecurityDeleteRoleService(client *Client) *XPackSecurityDeleteRoleService {\n\treturn &XPackSecurityDeleteRoleService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityDeleteRoleService) Pretty(pretty bool) *XPackSecurityDeleteRoleService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityDeleteRoleService) Human(human bool) *XPackSecurityDeleteRoleService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityDeleteRoleService) ErrorTrace(errorTrace bool) *XPackSecurityDeleteRoleService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityDeleteRoleService) FilterPath(filterPath ...string) *XPackSecurityDeleteRoleService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityDeleteRoleService) Header(name string, value string) *XPackSecurityDeleteRoleService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityDeleteRoleService) Headers(headers http.Header) *XPackSecurityDeleteRoleService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is name of the role to delete.\nfunc (s *XPackSecurityDeleteRoleService) Name(name string) *XPackSecurityDeleteRoleService {\n\ts.name = name\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityDeleteRoleService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/role/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityDeleteRoleService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityDeleteRoleService) Do(ctx context.Context) (*XPackSecurityDeleteRoleResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackSecurityDeleteRoleResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackSecurityDeleteRoleResponse is the response of XPackSecurityDeleteRoleService.Do.\ntype XPackSecurityDeleteRoleResponse struct {\n\tFound bool `json:\"found\"`\n}\n"
  },
  {
    "path": "xpack_security_delete_role_mapping.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityDeleteRoleMappingService delete a role mapping by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-delete-role-mapping.html.\ntype XPackSecurityDeleteRoleMappingService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname string\n}\n\n// NewXPackSecurityDeleteRoleMappingService creates a new XPackSecurityDeleteRoleMappingService.\nfunc NewXPackSecurityDeleteRoleMappingService(client *Client) *XPackSecurityDeleteRoleMappingService {\n\treturn &XPackSecurityDeleteRoleMappingService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityDeleteRoleMappingService) Pretty(pretty bool) *XPackSecurityDeleteRoleMappingService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityDeleteRoleMappingService) Human(human bool) *XPackSecurityDeleteRoleMappingService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityDeleteRoleMappingService) ErrorTrace(errorTrace bool) *XPackSecurityDeleteRoleMappingService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityDeleteRoleMappingService) FilterPath(filterPath ...string) *XPackSecurityDeleteRoleMappingService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityDeleteRoleMappingService) Header(name string, value string) *XPackSecurityDeleteRoleMappingService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityDeleteRoleMappingService) Headers(headers http.Header) *XPackSecurityDeleteRoleMappingService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is name of the role mapping to delete.\nfunc (s *XPackSecurityDeleteRoleMappingService) Name(name string) *XPackSecurityDeleteRoleMappingService {\n\ts.name = name\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityDeleteRoleMappingService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/role_mapping/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityDeleteRoleMappingService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityDeleteRoleMappingService) Do(ctx context.Context) (*XPackSecurityDeleteRoleMappingResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackSecurityDeleteRoleMappingResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackSecurityDeleteRoleMappingResponse is the response of XPackSecurityDeleteRoleMappingService.Do.\ntype XPackSecurityDeleteRoleMappingResponse struct {\n\tFound bool `json:\"found\"`\n}\n"
  },
  {
    "path": "xpack_security_delete_role_mapping_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityDeleteRoleMappingBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-role-mapping\",\n\t\t\t\"/_security/role_mapping/my-role-mapping\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityDeleteRoleMapping(test.Name)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_delete_role_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityDeleteRoleBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-role\",\n\t\t\t\"/_security/role/my-role\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityDeleteRole(test.Name)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_delete_user.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityDeleteUserService delete a user by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.4/security-api-delete-user.html.\ntype XPackSecurityDeleteUserService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tusername string\n\trefresh  string\n}\n\n// NewXPackSecurityDeleteUserService creates a new XPackSecurityDeleteUserService.\nfunc NewXPackSecurityDeleteUserService(client *Client) *XPackSecurityDeleteUserService {\n\treturn &XPackSecurityDeleteUserService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityDeleteUserService) Pretty(pretty bool) *XPackSecurityDeleteUserService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityDeleteUserService) Human(human bool) *XPackSecurityDeleteUserService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityDeleteUserService) ErrorTrace(errorTrace bool) *XPackSecurityDeleteUserService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityDeleteUserService) FilterPath(filterPath ...string) *XPackSecurityDeleteUserService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityDeleteUserService) Header(name string, value string) *XPackSecurityDeleteUserService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityDeleteUserService) Headers(headers http.Header) *XPackSecurityDeleteUserService {\n\ts.headers = headers\n\treturn s\n}\n\n// Username is name of the user to delete.\nfunc (s *XPackSecurityDeleteUserService) Username(username string) *XPackSecurityDeleteUserService {\n\ts.username = username\n\treturn s\n}\n\n// Refresh specifies if and how to wait for refreshing the shards after the request.\n// Possible values are \"true\" (default), \"false\" and \"wait_for\", all of type string.\nfunc (s *XPackSecurityDeleteUserService) Refresh(refresh string) *XPackSecurityDeleteUserService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityDeleteUserService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/user/{username}\", map[string]string{\n\t\t\"username\": s.username,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.refresh; v != \"\" {\n\t\tparams.Set(\"refresh\", v)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityDeleteUserService) Validate() error {\n\tvar invalid []string\n\tif s.username == \"\" {\n\t\tinvalid = append(invalid, \"Username\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityDeleteUserService) Do(ctx context.Context) (*XPackSecurityDeleteUserResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackSecurityDeleteUserResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackSecurityDeleteUserResponse is the response of XPackSecurityDeleteUserService.Do.\ntype XPackSecurityDeleteUserResponse struct {\n\tFound bool `json:\"found\"`\n}\n"
  },
  {
    "path": "xpack_security_delete_user_test.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityDeleteUserBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-user\",\n\t\t\t\"/_security/user/my-user\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityDeleteUser(test.Name)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_disable_user.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityDisableUserService retrieves a user by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-get-user.html.\ntype XPackSecurityDisableUserService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tusername string\n\trefresh  string\n}\n\n// NewXPackSecurityDisableUserService creates a new XPackSecurityDisableUserService.\nfunc NewXPackSecurityDisableUserService(client *Client) *XPackSecurityDisableUserService {\n\treturn &XPackSecurityDisableUserService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityDisableUserService) Pretty(pretty bool) *XPackSecurityDisableUserService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityDisableUserService) Human(human bool) *XPackSecurityDisableUserService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityDisableUserService) ErrorTrace(errorTrace bool) *XPackSecurityDisableUserService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityDisableUserService) FilterPath(filterPath ...string) *XPackSecurityDisableUserService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityDisableUserService) Header(name string, value string) *XPackSecurityDisableUserService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityDisableUserService) Headers(headers http.Header) *XPackSecurityDisableUserService {\n\ts.headers = headers\n\treturn s\n}\n\n// Username is name of the user to disable.\nfunc (s *XPackSecurityDisableUserService) Username(username string) *XPackSecurityDisableUserService {\n\ts.username = username\n\treturn s\n}\n\n// Refresh specifies if and how to wait for refreshing the shards after the request.\n// Possible values are \"true\" (default), \"false\" and \"wait_for\", all of type string.\nfunc (s *XPackSecurityDisableUserService) Refresh(refresh string) *XPackSecurityDisableUserService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityDisableUserService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/user/{username}/_disable\", map[string]string{\n\t\t\"username\": s.username,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.refresh; v != \"\" {\n\t\tparams.Set(\"refresh\", v)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityDisableUserService) Validate() error {\n\tvar invalid []string\n\tif s.username == \"\" {\n\t\tinvalid = append(invalid, \"Username\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityDisableUserService) Do(ctx context.Context) (*XPackSecurityDisableUserResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod: \"PUT\",\n\t\tPath:   path,\n\t\tParams: params,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackSecurityDisableUserResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackSecurityDisableUserResponse is the response of XPackSecurityDisableUserService.Do.\ntype XPackSecurityDisableUserResponse struct {\n}\n"
  },
  {
    "path": "xpack_security_disable_user_test.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityDisableUserBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-user\",\n\t\t\t\"/_security/user/my-user/_disable\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityDisableUser(test.Name)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_enable_user.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityEnableUserService retrieves a user by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-get-user.html.\ntype XPackSecurityEnableUserService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tusername string\n\trefresh  string\n}\n\n// NewXPackSecurityEnableUserService creates a new XPackSecurityEnableUserService.\nfunc NewXPackSecurityEnableUserService(client *Client) *XPackSecurityEnableUserService {\n\treturn &XPackSecurityEnableUserService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityEnableUserService) Pretty(pretty bool) *XPackSecurityEnableUserService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityEnableUserService) Human(human bool) *XPackSecurityEnableUserService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityEnableUserService) ErrorTrace(errorTrace bool) *XPackSecurityEnableUserService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityEnableUserService) FilterPath(filterPath ...string) *XPackSecurityEnableUserService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityEnableUserService) Header(name string, value string) *XPackSecurityEnableUserService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityEnableUserService) Headers(headers http.Header) *XPackSecurityEnableUserService {\n\ts.headers = headers\n\treturn s\n}\n\n// Username is name of the user to enable.\nfunc (s *XPackSecurityEnableUserService) Username(username string) *XPackSecurityEnableUserService {\n\ts.username = username\n\treturn s\n}\n\n// Refresh specifies if and how to wait for refreshing the shards after the request.\n// Possible values are \"true\" (default), \"false\" and \"wait_for\", all of type string.\nfunc (s *XPackSecurityEnableUserService) Refresh(refresh string) *XPackSecurityEnableUserService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityEnableUserService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/user/{username}/_enable\", map[string]string{\n\t\t\"username\": s.username,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.refresh; v != \"\" {\n\t\tparams.Set(\"refresh\", v)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityEnableUserService) Validate() error {\n\tvar invalid []string\n\tif s.username == \"\" {\n\t\tinvalid = append(invalid, \"Username\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityEnableUserService) Do(ctx context.Context) (*XPackSecurityEnableUserResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod: \"PUT\",\n\t\tPath:   path,\n\t\tParams: params,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackSecurityEnableUserResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackSecurityEnableUserResponse is the response of XPackSecurityEnableUserService.Do.\ntype XPackSecurityEnableUserResponse struct {\n}\n"
  },
  {
    "path": "xpack_security_enable_user_test.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityEnableUserBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-user\",\n\t\t\t\"/_security/user/my-user/_enable\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityEnableUser(test.Name)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_get_role.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityGetRoleService retrieves a role by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-get-role.html.\ntype XPackSecurityGetRoleService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname string\n}\n\n// NewXPackSecurityGetRoleService creates a new XPackSecurityGetRoleService.\nfunc NewXPackSecurityGetRoleService(client *Client) *XPackSecurityGetRoleService {\n\treturn &XPackSecurityGetRoleService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityGetRoleService) Pretty(pretty bool) *XPackSecurityGetRoleService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityGetRoleService) Human(human bool) *XPackSecurityGetRoleService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityGetRoleService) ErrorTrace(errorTrace bool) *XPackSecurityGetRoleService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityGetRoleService) FilterPath(filterPath ...string) *XPackSecurityGetRoleService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityGetRoleService) Header(name string, value string) *XPackSecurityGetRoleService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityGetRoleService) Headers(headers http.Header) *XPackSecurityGetRoleService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is name of the role to retrieve.\nfunc (s *XPackSecurityGetRoleService) Name(name string) *XPackSecurityGetRoleService {\n\ts.name = name\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityGetRoleService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/role/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityGetRoleService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityGetRoleService) Do(ctx context.Context) (*XPackSecurityGetRoleResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := XPackSecurityGetRoleResponse{}\n\tif err := json.Unmarshal(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &ret, nil\n}\n\n// XPackSecurityGetRoleResponse is the response of XPackSecurityGetRoleService.Do.\ntype XPackSecurityGetRoleResponse map[string]XPackSecurityRole\n\n// XPackSecurityRole is the role object.\n//\n// The Java source for this struct is defined here:\n// https://github.com/elastic/elasticsearch/blob/6.7/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/RoleDescriptor.java\ntype XPackSecurityRole struct {\n\tCluster           []string                             `json:\"cluster\"`\n\tIndices           []XPackSecurityIndicesPermissions    `json:\"indices\"`\n\tApplications      []XPackSecurityApplicationPrivileges `json:\"applications\"`\n\tRunAs             []string                             `json:\"run_as\"`\n\tGlobal            map[string]interface{}               `json:\"global\"`\n\tMetadata          map[string]interface{}               `json:\"metadata\"`\n\tTransientMetadata map[string]interface{}               `json:\"transient_metadata\"`\n}\n\n// XPackSecurityApplicationPrivileges is the application privileges object\ntype XPackSecurityApplicationPrivileges struct {\n\tApplication string   `json:\"application\"`\n\tPrivileges  []string `json:\"privileges\"`\n\tResources  []string `json:\"resources\"`\n}\n\n// XPackSecurityIndicesPermissions is the indices permission object\ntype XPackSecurityIndicesPermissions struct {\n\tNames         []string    `json:\"names\"`\n\tPrivileges    []string    `json:\"privileges\"`\n\tFieldSecurity interface{} `json:\"field_security,omitempty\"`\n\tQuery         string      `json:\"query\"`\n}\n"
  },
  {
    "path": "xpack_security_get_role_mapping.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityGetRoleMappingService retrieves a role mapping by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-get-role-mapping.html.\ntype XPackSecurityGetRoleMappingService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname string\n}\n\n// NewXPackSecurityGetRoleMappingService creates a new XPackSecurityGetRoleMappingService.\nfunc NewXPackSecurityGetRoleMappingService(client *Client) *XPackSecurityGetRoleMappingService {\n\treturn &XPackSecurityGetRoleMappingService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityGetRoleMappingService) Pretty(pretty bool) *XPackSecurityGetRoleMappingService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityGetRoleMappingService) Human(human bool) *XPackSecurityGetRoleMappingService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityGetRoleMappingService) ErrorTrace(errorTrace bool) *XPackSecurityGetRoleMappingService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityGetRoleMappingService) FilterPath(filterPath ...string) *XPackSecurityGetRoleMappingService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityGetRoleMappingService) Header(name string, value string) *XPackSecurityGetRoleMappingService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityGetRoleMappingService) Headers(headers http.Header) *XPackSecurityGetRoleMappingService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is name of the role mapping to retrieve.\nfunc (s *XPackSecurityGetRoleMappingService) Name(name string) *XPackSecurityGetRoleMappingService {\n\ts.name = name\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityGetRoleMappingService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/role_mapping/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityGetRoleMappingService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityGetRoleMappingService) Do(ctx context.Context) (*XPackSecurityGetRoleMappingResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := XPackSecurityGetRoleMappingResponse{}\n\tif err := json.Unmarshal(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &ret, nil\n}\n\n// XPackSecurityGetRoleMappingResponse is the response of XPackSecurityGetRoleMappingService.Do.\ntype XPackSecurityGetRoleMappingResponse map[string]XPackSecurityRoleMapping\n\n// XPackSecurityRoleMapping is the role mapping object\ntype XPackSecurityRoleMapping struct {\n\tEnabled  bool                   `json:\"enabled\"`\n\tRoles    []string               `json:\"roles\"`\n\tRules    map[string]interface{} `json:\"rules\"`\n\tMetadata interface{}            `json:\"metadata\"`\n}\n"
  },
  {
    "path": "xpack_security_get_role_mapping_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityGetRoleMappingBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-role-mapping\",\n\t\t\t\"/_security/role_mapping/my-role-mapping\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityGetRoleMapping(test.Name)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_get_role_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityGetRoleBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-role\",\n\t\t\t\"/_security/role/my-role\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityGetRole(test.Name)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_get_user.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityGetUserService retrieves a user by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-get-user.html.\ntype XPackSecurityGetUserService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tusernames []string\n}\n\n// NewXPackSecurityGetUserService creates a new XPackSecurityGetUserService.\nfunc NewXPackSecurityGetUserService(client *Client) *XPackSecurityGetUserService {\n\treturn &XPackSecurityGetUserService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty indicates that the JSON response be indented and human readable.\nfunc (s *XPackSecurityGetUserService) Pretty(pretty bool) *XPackSecurityGetUserService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityGetUserService) Human(human bool) *XPackSecurityGetUserService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityGetUserService) ErrorTrace(errorTrace bool) *XPackSecurityGetUserService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityGetUserService) FilterPath(filterPath ...string) *XPackSecurityGetUserService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityGetUserService) Header(name string, value string) *XPackSecurityGetUserService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityGetUserService) Headers(headers http.Header) *XPackSecurityGetUserService {\n\ts.headers = headers\n\treturn s\n}\n\n// Usernames are the names of one or more users to retrieve.\nfunc (s *XPackSecurityGetUserService) Usernames(usernames ...string) *XPackSecurityGetUserService {\n\tfor _, username := range usernames {\n\t\tif v := strings.TrimSpace(username); v != \"\" {\n\t\t\ts.usernames = append(s.usernames, v)\n\t\t}\n\t}\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityGetUserService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\tif len(s.usernames) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_security/user/{username}\", map[string]string{\n\t\t\t\"username\": strings.Join(s.usernames, \",\"),\n\t\t})\n\t} else {\n\t\tpath = \"/_security/user\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityGetUserService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityGetUserService) Do(ctx context.Context) (*XPackSecurityGetUserResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := XPackSecurityGetUserResponse{}\n\tif err := json.Unmarshal(res.Body, &ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn &ret, nil\n}\n\n// XPackSecurityGetUserResponse is the response of XPackSecurityGetUserService.Do.\ntype XPackSecurityGetUserResponse map[string]XPackSecurityUser\n\n// XPackSecurityUser is the user object.\n//\n// The Java source for this struct is defined here:\n// https://github.com/elastic/elasticsearch/blob/7.3/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/User.java\ntype XPackSecurityUser struct {\n\tUsername string                 `json:\"username\"`\n\tRoles    []string               `json:\"roles\"`\n\tFullname string                 `json:\"full_name\"`\n\tEmail    string                 `json:\"email\"`\n\tMetadata map[string]interface{} `json:\"metadata\"`\n\tEnabled  bool                   `json:\"enabled\"`\n}\n"
  },
  {
    "path": "xpack_security_get_user_test.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityGetUserBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"/_security/user\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"my-user\",\n\t\t\t\"/_security/user/my-user\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityGetUser(test.Name)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_put_role.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityPutRoleService retrieves a role by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-put-role.html.\ntype XPackSecurityPutRoleService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname string\n\tbody interface{}\n}\n\n// NewXPackSecurityPutRoleService creates a new XPackSecurityPutRoleService.\nfunc NewXPackSecurityPutRoleService(client *Client) *XPackSecurityPutRoleService {\n\treturn &XPackSecurityPutRoleService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityPutRoleService) Pretty(pretty bool) *XPackSecurityPutRoleService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityPutRoleService) Human(human bool) *XPackSecurityPutRoleService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityPutRoleService) ErrorTrace(errorTrace bool) *XPackSecurityPutRoleService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityPutRoleService) FilterPath(filterPath ...string) *XPackSecurityPutRoleService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityPutRoleService) Header(name string, value string) *XPackSecurityPutRoleService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityPutRoleService) Headers(headers http.Header) *XPackSecurityPutRoleService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is name of the role to create.\nfunc (s *XPackSecurityPutRoleService) Name(name string) *XPackSecurityPutRoleService {\n\ts.name = name\n\treturn s\n}\n\n// Body specifies the role. Use a string or a type that will get serialized as JSON.\nfunc (s *XPackSecurityPutRoleService) Body(body interface{}) *XPackSecurityPutRoleService {\n\ts.body = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityPutRoleService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/role/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityPutRoleService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif s.body == nil {\n\t\tinvalid = append(invalid, \"Body\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityPutRoleService) Do(ctx context.Context) (*XPackSecurityPutRoleResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    s.body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackSecurityPutRoleResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackSecurityPutRoleResponse is the response of XPackSecurityPutRoleService.Do.\ntype XPackSecurityPutRoleResponse struct {\n\tRole XPackSecurityPutRole\n}\n\ntype XPackSecurityPutRole struct {\n\tCreated bool `json:\"created\"`\n}\n"
  },
  {
    "path": "xpack_security_put_role_mapping.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityPutRoleMappingService create or update a role mapping by its name.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/security-api-put-role-mapping.html.\ntype XPackSecurityPutRoleMappingService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tname string\n\tbody interface{}\n}\n\n// NewXPackSecurityPutRoleMappingService creates a new XPackSecurityPutRoleMappingService.\nfunc NewXPackSecurityPutRoleMappingService(client *Client) *XPackSecurityPutRoleMappingService {\n\treturn &XPackSecurityPutRoleMappingService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityPutRoleMappingService) Pretty(pretty bool) *XPackSecurityPutRoleMappingService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityPutRoleMappingService) Human(human bool) *XPackSecurityPutRoleMappingService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityPutRoleMappingService) ErrorTrace(errorTrace bool) *XPackSecurityPutRoleMappingService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityPutRoleMappingService) FilterPath(filterPath ...string) *XPackSecurityPutRoleMappingService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityPutRoleMappingService) Header(name string, value string) *XPackSecurityPutRoleMappingService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityPutRoleMappingService) Headers(headers http.Header) *XPackSecurityPutRoleMappingService {\n\ts.headers = headers\n\treturn s\n}\n\n// Name is name of the role mapping to create/update.\nfunc (s *XPackSecurityPutRoleMappingService) Name(name string) *XPackSecurityPutRoleMappingService {\n\ts.name = name\n\treturn s\n}\n\n// Body specifies the role mapping. Use a string or a type that will get serialized as JSON.\nfunc (s *XPackSecurityPutRoleMappingService) Body(body interface{}) *XPackSecurityPutRoleMappingService {\n\ts.body = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityPutRoleMappingService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/role_mapping/{name}\", map[string]string{\n\t\t\"name\": s.name,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityPutRoleMappingService) Validate() error {\n\tvar invalid []string\n\tif s.name == \"\" {\n\t\tinvalid = append(invalid, \"Name\")\n\t}\n\tif s.body == nil {\n\t\tinvalid = append(invalid, \"Body\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityPutRoleMappingService) Do(ctx context.Context) (*XPackSecurityPutRoleMappingResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    s.body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackSecurityPutRoleMappingResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackSecurityPutRoleMappingResponse is the response of XPackSecurityPutRoleMappingService.Do.\ntype XPackSecurityPutRoleMappingResponse struct {\n\tRole_Mapping XPackSecurityPutRoleMapping\n}\n\ntype XPackSecurityPutRoleMapping struct {\n\tCreated bool `json:\"created\"`\n}\n"
  },
  {
    "path": "xpack_security_put_role_mapping_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityPutRoleMappingBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tBody         interface{}\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-role-mapping\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"\",\n\t\t\t`{}`,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-role-mapping\",\n\t\t\t`{}`,\n\t\t\t\"/_security/role_mapping/my-role-mapping\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityPutRoleMapping(test.Name).Body(test.Body)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_put_role_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityPutRoleBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tBody         interface{}\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-role\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"\",\n\t\t\t`{}`,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-role\",\n\t\t\t`{}`,\n\t\t\t\"/_security/role/my-role\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityPutRole(test.Name).Body(test.Body)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_security_put_user.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackSecurityPutUserService adds a user.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.4/security-api-put-user.html.\ntype XPackSecurityPutUserService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tusername string\n\trefresh  string\n\n\tuser *XPackSecurityPutUserRequest\n\tbody interface{}\n}\n\n// NewXPackSecurityPutUserService creates a new XPackSecurityPutUserService.\nfunc NewXPackSecurityPutUserService(client *Client) *XPackSecurityPutUserService {\n\treturn &XPackSecurityPutUserService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackSecurityPutUserService) Pretty(pretty bool) *XPackSecurityPutUserService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackSecurityPutUserService) Human(human bool) *XPackSecurityPutUserService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackSecurityPutUserService) ErrorTrace(errorTrace bool) *XPackSecurityPutUserService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackSecurityPutUserService) FilterPath(filterPath ...string) *XPackSecurityPutUserService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackSecurityPutUserService) Header(name string, value string) *XPackSecurityPutUserService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackSecurityPutUserService) Headers(headers http.Header) *XPackSecurityPutUserService {\n\ts.headers = headers\n\treturn s\n}\n\n// Username is the name of the user to add.\nfunc (s *XPackSecurityPutUserService) Username(username string) *XPackSecurityPutUserService {\n\ts.username = username\n\treturn s\n}\n\n// User specifies the data of the new user.\n//\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.4/security-api-put-user.html\n// for details.\nfunc (s *XPackSecurityPutUserService) User(user *XPackSecurityPutUserRequest) *XPackSecurityPutUserService {\n\ts.user = user\n\treturn s\n}\n\n// Refresh specifies if and how to wait for refreshing the shards after the request.\n// Possible values are \"true\" (default), \"false\" and \"wait_for\", all of type string.\nfunc (s *XPackSecurityPutUserService) Refresh(refresh string) *XPackSecurityPutUserService {\n\ts.refresh = refresh\n\treturn s\n}\n\n// Body specifies the user. Use a string or a type that will get serialized as JSON.\nfunc (s *XPackSecurityPutUserService) Body(body interface{}) *XPackSecurityPutUserService {\n\ts.body = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackSecurityPutUserService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_security/user/{username}\", map[string]string{\n\t\t\"username\": s.username,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.refresh; v != \"\" {\n\t\tparams.Set(\"refresh\", v)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackSecurityPutUserService) Validate() error {\n\tvar invalid []string\n\tif s.username == \"\" {\n\t\tinvalid = append(invalid, \"Username\")\n\t}\n\tif s.user == nil && s.body == nil {\n\t\tinvalid = append(invalid, \"User\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackSecurityPutUserService) Do(ctx context.Context) (*XPackSecurityPutUserResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar body interface{}\n\tif s.user != nil {\n\t\tbody = s.user\n\t} else {\n\t\tbody = s.body\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod: \"PUT\",\n\t\tPath:   path,\n\t\tParams: params,\n\t\tBody:   body,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackSecurityPutUserResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackSecurityPutUserRequest specifies the data required/allowed to add\n// a new user.\ntype XPackSecurityPutUserRequest struct {\n\tEnabled      bool                   `json:\"enabled\"`\n\tEmail        string                 `json:\"email,omitempty\"`\n\tFullName     string                 `json:\"full_name,omitempty\"`\n\tMetadata     map[string]interface{} `json:\"metadata,omitempty\"`\n\tPassword     string                 `json:\"password,omitempty\"`\n\tPasswordHash string                 `json:\"password_hash,omitempty\"`\n\tRoles        []string               `json:\"roles\"`\n}\n\n// XPackSecurityPutUserResponse is the response of XPackSecurityPutUserService.Do.\ntype XPackSecurityPutUserResponse struct {\n\tCreated bool `json:\"created\"`\n}\n"
  },
  {
    "path": "xpack_security_put_user_test.go",
    "content": "// Copyright 2012-2019 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackSecurityPutUserBuildURL(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\ttests := []struct {\n\t\tName         string\n\t\tBody         interface{}\n\t\tExpectedPath string\n\t\tExpectErr    bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-user\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"\",\n\t\t\t`{}`,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-user\",\n\t\t\t`{}`,\n\t\t\t\"/_security/user/my-user\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackSecurityPutUser(test.Name).Body(test.Body)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.ExpectedPath {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.ExpectedPath, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_test.go",
    "content": "package elastic\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n)\n\nconst (\n\ttestRoleBody = `{\n\t\t\"cluster\" : [ \"all\" ],\n\t\t\"indices\" : [\n\t\t\t{\n\t\t\t\t\"names\" : [ \"index1\", \"index2\" ],\n\t\t\t\t\"privileges\" : [ \"all\" ],\n\t\t\t\t\"field_security\" : {\n\t\t\t\t\t\"grant\" : [ \"title\", \"body\" ]\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\t\"applications\" : [ ],\n\t\t\"run_as\" : [ \"other_user\" ],\n\t\t\"global\" : {\n\t\t\t\"application\": {\n\t\t\t  \"manage\": {\n\t\t\t\t  \"applications\": [ \"my-test-app\" ]\n\t\t\t  }\n\t\t\t}\n\t\t  },\n\t\t\"metadata\" : {\n\t\t\t\"version\" : 1\n\t\t},\n\t\t\"transient_metadata\": {\n\t\t\t\"enabled\": true\n\t\t}\n\t  }`\n\n\ttestRoleMappingBody = `{\n\t\t\"enabled\": false,\n\t\t\"roles\": [\n\t\t\t\"user\"\n\t\t],\n\t\t\"rules\": {\n\t\t\t\"all\": [\n\t\t\t\t{\n\t\t\t\t\t\"field\": {\n\t\t\t\t\t\"username\": \"esadmin\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"field\": {\n\t\t\t\t\t\"groups\": \"cn=admins,dc=example,dc=com\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t\"metadata\": {\n\t\t\t\"version\": 1\n\t\t}\n\t  }`\n\n\ttestUserBody = `{\n\t\t\"password\": \"secret\",\n\t\t\"roles\": [\"admin\"]\n\t}`\n\ttestWatchBody = `{\n\t\t\"trigger\" : {\n\t\t\t\"schedule\" : { \"cron\" : \"0 0/1 * * * ?\" }\n\t\t},\n\t\t\"input\" : {\n\t\t\t\"search\" : {\n\t\t\t\t\"request\" : {\n\t\t\t\t\t\"indices\" : [\n\t\t\t\t\t\t\"elastic-test\"\n\t\t\t\t\t],\n\t\t\t\t\t\"body\" : {\n\t\t\t\t\t\t\"query\" : {\n\t\t\t\t\t\t\t\"bool\" : {\n\t\t\t\t\t\t\t\t\"must\" : {\n\t\t\t\t\t\t\t\t\t\"match\": {\n\t\t\t\t\t\t\t\t\t\t \"response\": 404\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"filter\" : {\n\t\t\t\t\t\t\t\t\t\"range\": {\n\t\t\t\t\t\t\t\t\t\t\"@timestamp\": {\n\t\t\t\t\t\t\t\t\t\t\t\"from\": \"{{ctx.trigger.scheduled_time}}||-5m\",\n\t\t\t\t\t\t\t\t\t\t\t\"to\": \"{{ctx.trigger.triggered_time}}\"\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"condition\" : {\n\t\t\t\"compare\" : { \"ctx.payload.hits.total\" : { \"gt\" : 0 }}\n\t\t},\n\t\t\"actions\" : {\n\t\t\t\"email_admin\" : {\n\t\t\t\t\"email\" : {\n\t\t\t\t\t\"to\" : \"admin@domain.host.com\",\n\t\t\t\t\t\"subject\" : \"404 recently encountered\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}`\n\ttestRollupBody = `{\n\t\t\"index_pattern\": \"elastic-orders\",\n\t\t\"rollup_index\": \"orders-rollup\",\n\t\t\"cron\": \"*/30 * * * * ?\",\n\t\t\"page_size\" :1000,\n\t\t\"groups\" : {\n\t\t\t\"date_histogram\": {\n\t\t\t\t\"field\": \"time\",\n\t\t\t\t\"interval\": \"1h\",\n\t\t\t\t\"delay\": \"7d\"\n\t\t\t},\n\t\t\t\"terms\": {\n\t\t\t\t\"fields\": [\"manufacturer\"]\n\t\t\t}\n\t\t},\n\t\t\"metrics\": [\n\t\t\t{\n\t\t\t\t\"field\": \"price\",\n\t\t\t\t\"metrics\": [\"min\", \"max\", \"sum\"]\n\t\t\t}\n\t\t]\n\t}`\n)\n\nfunc TestXpackInfo(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\ttagline := \"You know, for X\"\n\n\t// Get xpack info\n\tinfo, err := client.XPackInfo().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif info == &(XPackInfoServiceResponse{}) {\n\t\tt.Errorf(\"expected data from response; got empty response\")\n\t}\n\tif info.Tagline != tagline {\n\t\tt.Errorf(\"expected %s as a tagline; received %s\", tagline, info.Tagline)\n\t}\n}\n\nfunc TestXPackSecurityRole(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\txpack_info, err := client.XPackInfo().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !xpack_info.Features.Security.Enabled {\n\t\tt.Skip(\"skip due to deactivated xpack security\")\n\t}\n\n\troleName := \"my-role\"\n\n\t// Add a role\n\t_, err = client.XPackSecurityPutRole(roleName).Body(testRoleBody).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tclient.XPackSecurityDeleteRole(roleName).Do(context.Background())\n\t}()\n\n\t// Get a role\n\trole, err := client.XPackSecurityGetRole(roleName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(*role) == 0 {\n\t\tt.Errorf(\"expected len(Mappings) > 0; got empty\")\n\t}\n\tif _, ok := (*role)[roleName]; !ok {\n\t\tt.Errorf(\"expected role mapping %s; key did not exist\", roleName)\n\t}\n\tif role == &(XPackSecurityGetRoleResponse{}) {\n\t\tt.Errorf(\"expected data from response; got empty response\")\n\t}\n\n\t// Delete a role\n\tdeletedRole, err := client.XPackSecurityDeleteRole(roleName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !deletedRole.Found {\n\t\tt.Error(\"expected test role to be found; was not found\")\n\t}\n\n}\n\nfunc TestXPackSecurityRoleMapping(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\txpack_info, err := client.XPackInfo().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !xpack_info.Features.Security.Enabled {\n\t\tt.Skip(\"skip due to deactivated xpack security\")\n\t}\n\n\troleMappingName := \"my-role-mapping\"\n\n\t// Add a role mapping\n\t_, err = client.XPackSecurityPutRoleMapping(roleMappingName).Body(testRoleMappingBody).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tclient.XPackSecurityDeleteRoleMapping(roleMappingName).Do(context.Background())\n\t}()\n\n\t// Get a role mapping\n\troleMappings, err := client.XPackSecurityGetRoleMapping(roleMappingName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(*roleMappings) == 0 {\n\t\tt.Errorf(\"expected len(Mappings) > 0; got empty\")\n\t}\n\tif _, ok := (*roleMappings)[roleMappingName]; !ok {\n\t\tt.Errorf(\"expected role mapping %s; key did not exist\", roleMappingName)\n\t}\n\tif roleMappings == &(XPackSecurityGetRoleMappingResponse{}) {\n\t\tt.Errorf(\"expected data from response; got empty response\")\n\t}\n\n\t// Delete a role mapping\n\t_, err = client.XPackSecurityDeleteRoleMapping(roleMappingName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n}\n\nfunc TestXPackSecurityUser(t *testing.T) {\n\tclient := setupTestClientForXpackSecurity(t)\n\n\txpackInfo, err := client.XPackInfo().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !xpackInfo.Features.Security.Enabled {\n\t\tt.Skip(\"skip due to deactivated xpack security\")\n\t}\n\n\tusername := \"john\"\n\n\t// Add a user\n\tcreateResp, err := client.XPackSecurityPutUser(username).Body(testUserBody).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif createResp == nil {\n\t\tt.Fatal(\"expected to create user\")\n\t}\n\tif want, have := true, createResp.Created; want != have {\n\t\tt.Fatalf(\"want Created=%v, have %v\", want, have)\n\t}\n\tdefer func() {\n\t\tclient.XPackSecurityDeleteUser(username).Do(context.Background())\n\t}()\n\n\t// Get a user\n\tuser, err := client.XPackSecurityGetUser(username).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(*user) == 0 {\n\t\tt.Errorf(\"expected len(Mappings) > 0; got empty\")\n\t}\n\tif _, ok := (*user)[username]; !ok {\n\t\tt.Errorf(\"expected user mapping %s; key did not exist\", username)\n\t}\n\tif user == &(XPackSecurityGetUserResponse{}) {\n\t\tt.Errorf(\"expected data from response; got empty response\")\n\t}\n\t// Disable a user\n\t_, err = client.XPackSecurityDisableUser(username).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tuser, err = client.XPackSecurityGetUser(username).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif (*user)[username].Enabled {\n\t\tt.Error(\"expected test user to be disabled; was still enabled\")\n\t}\n\t// Enable a user\n\t_, err = client.XPackSecurityEnableUser(username).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tuser, err = client.XPackSecurityGetUser(username).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !(*user)[username].Enabled {\n\t\tt.Error(\"expected test user to be enabled; was still disabled\")\n\t}\n\n\t// Delete a user\n\tdeletedUser, err := client.XPackSecurityDeleteUser(username).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !deletedUser.Found {\n\t\tt.Error(\"expected test user to be found; was not found\")\n\t}\n\n}\n\nfunc TestXPackWatcher(t *testing.T) {\n\tclient := setupTestClientAndCreateIndex(t, SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\txpack_info, err := client.XPackInfo().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !xpack_info.Features.Watcher.Enabled {\n\t\tt.Skip(\"skip due to deactivated xpack watcher\")\n\t}\n\n\t// Add a watch\n\twatchName := \"my-watch\"\n\t_, err = client.XPackWatchPut(watchName).Body(testWatchBody).Do(context.Background())\n\tif err != nil {\n\t\tif IsForbidden(err) {\n\t\t\tt.Skipf(\"skip due to missing license: %v\", err)\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tclient.XPackWatchDelete(watchName).Do(context.Background())\n\t}()\n\n\t// Get a watch\n\twatch, err := client.XPackWatchGet(watchName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif watch.Found == false {\n\t\tt.Errorf(\"expected watch.Found == true; got false\")\n\t}\n\tif want, have := watchName, watch.Id; want != have {\n\t\tt.Errorf(\"expected watch.Id == %q; got %q\", want, have)\n\t}\n\n\t// Exec a watch\n\texecution, err := client.XPackWatchExecute().Id(watchName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := watchName, execution.WatchRecord.WatchId; want != have {\n\t\tt.Errorf(\"expected execution.WatchId == %q; got %q\", want, have)\n\t}\n\tif want, have := \"execution_not_needed\", execution.WatchRecord.State; want != have {\n\t\tt.Errorf(\"expected execution.state == %q; got %q\", want, have)\n\t}\n\n\t// Ack a watch\n\tack, err := client.XPackWatchAck(watchName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif ack.Status.State == nil {\n\t\tt.Errorf(\"expected ack.status != nil; got %v\", ack.Status.State)\n\t}\n\n\t// Activate a watch\n\t_, err = client.XPackWatchActivate(watchName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twatch, err = client.XPackWatchGet(watchName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := true, watch.Status.State.Active; want != have {\n\t\tt.Errorf(\"expected watch.Status.State.Active == %v; got %v\", want, have)\n\t}\n\n\t// Deactivate the watch\n\t_, err = client.XPackWatchDeactivate(watchName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\twatch, err = client.XPackWatchGet(watchName).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := false, watch.Status.State.Active; want != have {\n\t\tt.Errorf(\"expected watch.Status.State.Active == %v; got %v\", want, have)\n\t}\n\n\t// Stop the watch\n\t_, err = client.XPackWatchStop().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tstats, err := client.XPackWatchStats().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif have := stats.Stats[0].WatcherState; have != \"stopping\" && have != \"stopped\" {\n\t\tt.Errorf(\"expected stats.WatcherState == %q (or %q); got %q\", \"stopping\", \"stopped\", have)\n\t}\n\n\t// Start again\n\tstart, err := client.XPackWatchStart().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\t_, err = client.XPackWatchStats().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := true, start.Acknowledged; want != have {\n\t\tt.Errorf(\"expected start.Acknowledged == %v; got %v\", want, have)\n\t}\n}\n\nfunc TestXPackRollup(t *testing.T) {\n\tclient := setupTestClientAndCreateIndexAndAddDocs(t, SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\txpack_info, err := client.XPackInfo().Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif !xpack_info.Features.Rollup.Enabled {\n\t\tt.Skip(\"skip due to deactivated xpack rollup\")\n\t}\n\n\t// Adding timestamp to the job id here to improve test re-run ablity, relates to issue where rollup jobs are\n\t// not cleanly removed leaving _meta behind. https://github.com/elastic/elasticsearch/issues/31347\n\tjobId := fmt.Sprintf(\"my-job-%d\", time.Now().Unix())\n\n\t// Add a rollup job\n\t_, err = client.XPackRollupPut(jobId).Body(testRollupBody).Do(context.Background())\n\tif err != nil {\n\t\tif IsForbidden(err) {\n\t\t\tt.Skipf(\"skip due to missing license: %v\", err)\n\t\t}\n\t\tt.Fatal(err)\n\t}\n\tdefer func() {\n\t\tclient.XPackRollupDelete(jobId).Do(context.Background())\n\t}()\n\n\t// Get rollup jobs\n\tjobs, err := client.XPackRollupGet(jobId).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tif len(jobs.Jobs) != 1 {\n\t\tt.Errorf(\"expected len(jobs.Jobs) == 1; got %d\", len(jobs.Jobs))\n\t}\n\tif want, have := jobs.Jobs[0].Config.IndexPattern, \"elastic-orders\"; want != have {\n\t\tt.Errorf(\"expected IndexPattern == %q; got %q\", want, have)\n\t}\n\n\t// Start rollup job\n\t_, err = client.XPackRollupStart(jobId).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tjobs, err = client.XPackRollupGet(jobId).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := \"started\", jobs.Jobs[0].Status.JobState; want != have {\n\t\tt.Errorf(\"expected job.Status.JobState == %v; got %v\", want, have)\n\t}\n\n\t// Stop rollup job\n\t_, err = client.XPackRollupStop(jobId).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tjobs, err = client.XPackRollupGet(jobId).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif want, have := \"stopped\", jobs.Jobs[0].Status.JobState; want != have {\n\t\tt.Errorf(\"expected job.Status.JobState == %v; got %v\", want, have)\n\t}\n\n\t// Delete rollup job\n\t_, err = client.XPackRollupDelete(jobId).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\n\tjobs, err = client.XPackRollupGet(jobId).Do(context.Background())\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n\tif len(jobs.Jobs) > 0 {\n\t\tt.Errorf(\"expected len(jobs.Jobs) == 0; got %d\", len(jobs.Jobs))\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_ack_watch.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackWatcherAckWatchService enables you to manually throttle execution of the watch’s actions.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-ack-watch.html.\ntype XPackWatcherAckWatchService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\twatchId       string\n\tactionId      []string\n\tmasterTimeout string\n}\n\n// NewXPackWatcherAckWatchService creates a new XPackWatcherAckWatchService.\nfunc NewXPackWatcherAckWatchService(client *Client) *XPackWatcherAckWatchService {\n\treturn &XPackWatcherAckWatchService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherAckWatchService) Pretty(pretty bool) *XPackWatcherAckWatchService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherAckWatchService) Human(human bool) *XPackWatcherAckWatchService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherAckWatchService) ErrorTrace(errorTrace bool) *XPackWatcherAckWatchService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherAckWatchService) FilterPath(filterPath ...string) *XPackWatcherAckWatchService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherAckWatchService) Header(name string, value string) *XPackWatcherAckWatchService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherAckWatchService) Headers(headers http.Header) *XPackWatcherAckWatchService {\n\ts.headers = headers\n\treturn s\n}\n\n// WatchId is the unique ID of the watch.\nfunc (s *XPackWatcherAckWatchService) WatchId(watchId string) *XPackWatcherAckWatchService {\n\ts.watchId = watchId\n\treturn s\n}\n\n// ActionId is a slice of action ids to be acked.\nfunc (s *XPackWatcherAckWatchService) ActionId(actionId ...string) *XPackWatcherAckWatchService {\n\ts.actionId = append(s.actionId, actionId...)\n\treturn s\n}\n\n// MasterTimeout indicates an explicit operation timeout for\n// connection to master node.\nfunc (s *XPackWatcherAckWatchService) MasterTimeout(masterTimeout string) *XPackWatcherAckWatchService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherAckWatchService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\tif len(s.actionId) > 0 {\n\t\tpath, err = uritemplates.Expand(\"/_watcher/watch/{watch_id}/_ack/{action_id}\", map[string]string{\n\t\t\t\"watch_id\":  s.watchId,\n\t\t\t\"action_id\": strings.Join(s.actionId, \",\"),\n\t\t})\n\t} else {\n\t\tpath, err = uritemplates.Expand(\"/_watcher/watch/{watch_id}/_ack\", map[string]string{\n\t\t\t\"watch_id\": s.watchId,\n\t\t})\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherAckWatchService) Validate() error {\n\tvar invalid []string\n\tif s.watchId == \"\" {\n\t\tinvalid = append(invalid, \"WatchId\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherAckWatchService) Do(ctx context.Context) (*XPackWatcherAckWatchResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherAckWatchResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherAckWatchResponse is the response of XPackWatcherAckWatchService.Do.\ntype XPackWatcherAckWatchResponse struct {\n\tStatus *XPackWatcherAckWatchStatus `json:\"status\"`\n}\n\n// XPackWatcherAckWatchStatus is the status of a XPackWatcherAckWatchResponse.\ntype XPackWatcherAckWatchStatus struct {\n\tState            map[string]interface{}            `json:\"state\"`\n\tLastChecked      string                            `json:\"last_checked\"`\n\tLastMetCondition string                            `json:\"last_met_condition\"`\n\tActions          map[string]map[string]interface{} `json:\"actions\"`\n\tExecutionState   string                            `json:\"execution_state\"`\n\tVersion          int                               `json:\"version\"`\n}\n"
  },
  {
    "path": "xpack_watcher_ack_watch_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackWatcherAckWatchBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tWatchId   string\n\t\tActionId  []string\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t[]string{},\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\t[]string{},\n\t\t\t\"/_watcher/watch/my-watch/_ack\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\t[]string{\"action1\"},\n\t\t\t\"/_watcher/watch/my-watch/_ack/action1\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\t[]string{\"action1\", \"action2\"},\n\t\t\t\"/_watcher/watch/my-watch/_ack/action1%2Caction2\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchAck(test.WatchId).ActionId(test.ActionId...)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_activate_watch.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackWatcherActivateWatchService enables you to activate a currently inactive watch.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-activate-watch.html.\ntype XPackWatcherActivateWatchService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\twatchId       string\n\tmasterTimeout string\n}\n\n// NewXPackWatcherActivateWatchService creates a new XPackWatcherActivateWatchService.\nfunc NewXPackWatcherActivateWatchService(client *Client) *XPackWatcherActivateWatchService {\n\treturn &XPackWatcherActivateWatchService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherActivateWatchService) Pretty(pretty bool) *XPackWatcherActivateWatchService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherActivateWatchService) Human(human bool) *XPackWatcherActivateWatchService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherActivateWatchService) ErrorTrace(errorTrace bool) *XPackWatcherActivateWatchService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherActivateWatchService) FilterPath(filterPath ...string) *XPackWatcherActivateWatchService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherActivateWatchService) Header(name string, value string) *XPackWatcherActivateWatchService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherActivateWatchService) Headers(headers http.Header) *XPackWatcherActivateWatchService {\n\ts.headers = headers\n\treturn s\n}\n\n// WatchId is the ID of the watch to activate.\nfunc (s *XPackWatcherActivateWatchService) WatchId(watchId string) *XPackWatcherActivateWatchService {\n\ts.watchId = watchId\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *XPackWatcherActivateWatchService) MasterTimeout(masterTimeout string) *XPackWatcherActivateWatchService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherActivateWatchService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_watcher/watch/{watch_id}/_activate\", map[string]string{\n\t\t\"watch_id\": s.watchId,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherActivateWatchService) Validate() error {\n\tvar invalid []string\n\tif s.watchId == \"\" {\n\t\tinvalid = append(invalid, \"WatchId\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherActivateWatchService) Do(ctx context.Context) (*XPackWatcherActivateWatchResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherActivateWatchResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherActivateWatchResponse is the response of XPackWatcherActivateWatchService.Do.\ntype XPackWatcherActivateWatchResponse struct {\n\tStatus *XPackWatchStatus `json:\"status\"`\n}\n"
  },
  {
    "path": "xpack_watcher_activate_watch_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackWatcherActivateWatchBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tWatchId   string\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\t\"/_watcher/watch/my-watch/_activate\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchActivate(test.WatchId)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_deactivate_watch.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackWatcherDeactivateWatchService enables you to deactivate a currently active watch.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-deactivate-watch.html.\ntype XPackWatcherDeactivateWatchService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\twatchId       string\n\tmasterTimeout string\n}\n\n// NewXPackWatcherDeactivateWatchService creates a new XPackWatcherDeactivateWatchService.\nfunc NewXPackWatcherDeactivateWatchService(client *Client) *XPackWatcherDeactivateWatchService {\n\treturn &XPackWatcherDeactivateWatchService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherDeactivateWatchService) Pretty(pretty bool) *XPackWatcherDeactivateWatchService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherDeactivateWatchService) Human(human bool) *XPackWatcherDeactivateWatchService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherDeactivateWatchService) ErrorTrace(errorTrace bool) *XPackWatcherDeactivateWatchService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherDeactivateWatchService) FilterPath(filterPath ...string) *XPackWatcherDeactivateWatchService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherDeactivateWatchService) Header(name string, value string) *XPackWatcherDeactivateWatchService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherDeactivateWatchService) Headers(headers http.Header) *XPackWatcherDeactivateWatchService {\n\ts.headers = headers\n\treturn s\n}\n\n// WatchId is the ID of the watch to deactivate.\nfunc (s *XPackWatcherDeactivateWatchService) WatchId(watchId string) *XPackWatcherDeactivateWatchService {\n\ts.watchId = watchId\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *XPackWatcherDeactivateWatchService) MasterTimeout(masterTimeout string) *XPackWatcherDeactivateWatchService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherDeactivateWatchService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_watcher/watch/{watch_id}/_deactivate\", map[string]string{\n\t\t\"watch_id\": s.watchId,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherDeactivateWatchService) Validate() error {\n\tvar invalid []string\n\tif s.watchId == \"\" {\n\t\tinvalid = append(invalid, \"WatchId\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherDeactivateWatchService) Do(ctx context.Context) (*XPackWatcherDeactivateWatchResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherDeactivateWatchResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherDeactivateWatchResponse is the response of XPackWatcherDeactivateWatchService.Do.\ntype XPackWatcherDeactivateWatchResponse struct {\n\tStatus *XPackWatchStatus `json:\"status\"`\n}\n"
  },
  {
    "path": "xpack_watcher_deactivate_watch_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackWatcherDeactivateWatchBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tWatchId   string\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\t\"/_watcher/watch/my-watch/_deactivate\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchDeactivate(test.WatchId)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_delete_watch.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackWatcherDeleteWatchService removes a watch.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-delete-watch.html.\ntype XPackWatcherDeleteWatchService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid            string\n\tmasterTimeout string\n}\n\n// NewXPackWatcherDeleteWatchService creates a new XPackWatcherDeleteWatchService.\nfunc NewXPackWatcherDeleteWatchService(client *Client) *XPackWatcherDeleteWatchService {\n\treturn &XPackWatcherDeleteWatchService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherDeleteWatchService) Pretty(pretty bool) *XPackWatcherDeleteWatchService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherDeleteWatchService) Human(human bool) *XPackWatcherDeleteWatchService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherDeleteWatchService) ErrorTrace(errorTrace bool) *XPackWatcherDeleteWatchService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherDeleteWatchService) FilterPath(filterPath ...string) *XPackWatcherDeleteWatchService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherDeleteWatchService) Header(name string, value string) *XPackWatcherDeleteWatchService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherDeleteWatchService) Headers(headers http.Header) *XPackWatcherDeleteWatchService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id of the watch to delete.\nfunc (s *XPackWatcherDeleteWatchService) Id(id string) *XPackWatcherDeleteWatchService {\n\ts.id = id\n\treturn s\n}\n\n// MasterTimeout specifies an explicit operation timeout for connection to master node.\nfunc (s *XPackWatcherDeleteWatchService) MasterTimeout(masterTimeout string) *XPackWatcherDeleteWatchService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherDeleteWatchService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_watcher/watch/{id}\", map[string]string{\n\t\t\"id\": s.id,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherDeleteWatchService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherDeleteWatchService) Do(ctx context.Context) (*XPackWatcherDeleteWatchResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"DELETE\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherDeleteWatchResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherDeleteWatchResponse is the response of XPackWatcherDeleteWatchService.Do.\ntype XPackWatcherDeleteWatchResponse struct {\n\tFound   bool   `json:\"found\"`\n\tId      string `json:\"_id\"`\n\tVersion int    `json:\"_version\"`\n}\n"
  },
  {
    "path": "xpack_watcher_delete_watch_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackWatcherDeleteWatchBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tId        string\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\t\"/_watcher/watch/my-watch\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchDelete(test.Id)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_execute_watch.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackWatcherExecuteWatchService forces the execution of a stored watch.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-execute-watch.html.\ntype XPackWatcherExecuteWatchService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid         string\n\tdebug      *bool\n\tbodyJson   interface{}\n\tbodyString string\n}\n\n// NewXPackWatcherExecuteWatchService creates a new XPackWatcherExecuteWatchService.\nfunc NewXPackWatcherExecuteWatchService(client *Client) *XPackWatcherExecuteWatchService {\n\treturn &XPackWatcherExecuteWatchService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherExecuteWatchService) Pretty(pretty bool) *XPackWatcherExecuteWatchService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherExecuteWatchService) Human(human bool) *XPackWatcherExecuteWatchService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherExecuteWatchService) ErrorTrace(errorTrace bool) *XPackWatcherExecuteWatchService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherExecuteWatchService) FilterPath(filterPath ...string) *XPackWatcherExecuteWatchService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherExecuteWatchService) Header(name string, value string) *XPackWatcherExecuteWatchService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherExecuteWatchService) Headers(headers http.Header) *XPackWatcherExecuteWatchService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id of the watch to execute on.\nfunc (s *XPackWatcherExecuteWatchService) Id(id string) *XPackWatcherExecuteWatchService {\n\ts.id = id\n\treturn s\n}\n\n// Debug indicates whether the watch should execute in debug mode.\nfunc (s *XPackWatcherExecuteWatchService) Debug(debug bool) *XPackWatcherExecuteWatchService {\n\ts.debug = &debug\n\treturn s\n}\n\n// BodyJson is documented as: Execution control.\nfunc (s *XPackWatcherExecuteWatchService) BodyJson(body interface{}) *XPackWatcherExecuteWatchService {\n\ts.bodyJson = body\n\treturn s\n}\n\n// BodyString is documented as: Execution control.\nfunc (s *XPackWatcherExecuteWatchService) BodyString(body string) *XPackWatcherExecuteWatchService {\n\ts.bodyString = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherExecuteWatchService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tvar (\n\t\tpath string\n\t\terr  error\n\t)\n\tif s.id != \"\" {\n\t\tpath, err = uritemplates.Expand(\"/_watcher/watch/{id}/_execute\", map[string]string{\n\t\t\t\"id\": s.id,\n\t\t})\n\t} else {\n\t\tpath = \"/_watcher/watch/_execute\"\n\t}\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.debug; v != nil {\n\t\tparams.Set(\"debug\", fmt.Sprint(*v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherExecuteWatchService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherExecuteWatchService) Do(ctx context.Context) (*XPackWatcherExecuteWatchResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Setup HTTP request body\n\tvar body interface{}\n\tif s.bodyJson != nil {\n\t\tbody = s.bodyJson\n\t} else {\n\t\tbody = s.bodyString\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherExecuteWatchResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherExecuteWatchResponse is the response of XPackWatcherExecuteWatchService.Do.\ntype XPackWatcherExecuteWatchResponse struct {\n\tId          string            `json:\"_id\"`\n\tWatchRecord *XPackWatchRecord `json:\"watch_record\"`\n}\n\ntype XPackWatchRecord struct {\n\tWatchId   string                            `json:\"watch_id\"`\n\tNode      string                            `json:\"node\"`\n\tMessages  []string                          `json:\"messages\"`\n\tState     string                            `json:\"state\"`\n\tStatus    *XPackWatchRecordStatus           `json:\"status\"`\n\tInput     map[string]map[string]interface{} `json:\"input\"`\n\tCondition map[string]map[string]interface{} `json:\"condition\"`\n\tResult    map[string]interface{}            `json:\"Result\"`\n}\n\ntype XPackWatchRecordStatus struct {\n\tVersion          int                               `json:\"version\"`\n\tState            map[string]interface{}            `json:\"state\"`\n\tLastChecked      string                            `json:\"last_checked\"`\n\tLastMetCondition string                            `json:\"last_met_condition\"`\n\tActions          map[string]map[string]interface{} `json:\"actions\"`\n\tExecutionState   string                            `json:\"execution_state\"`\n}\n"
  },
  {
    "path": "xpack_watcher_execute_watch_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackWatcherExecuteWatchBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tId        string\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"/_watcher/watch/_execute\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\t\"/_watcher/watch/my-watch/_execute\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchExecute().Id(test.Id)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_get_watch.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackWatcherGetWatchService retrieves a watch by its ID.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-get-watch.html.\ntype XPackWatcherGetWatchService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid string\n}\n\n// NewXPackWatcherGetWatchService creates a new XPackWatcherGetWatchService.\nfunc NewXPackWatcherGetWatchService(client *Client) *XPackWatcherGetWatchService {\n\treturn &XPackWatcherGetWatchService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherGetWatchService) Pretty(pretty bool) *XPackWatcherGetWatchService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherGetWatchService) Human(human bool) *XPackWatcherGetWatchService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherGetWatchService) ErrorTrace(errorTrace bool) *XPackWatcherGetWatchService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherGetWatchService) FilterPath(filterPath ...string) *XPackWatcherGetWatchService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherGetWatchService) Header(name string, value string) *XPackWatcherGetWatchService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherGetWatchService) Headers(headers http.Header) *XPackWatcherGetWatchService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id is ID of the watch to retrieve.\nfunc (s *XPackWatcherGetWatchService) Id(id string) *XPackWatcherGetWatchService {\n\ts.id = id\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherGetWatchService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_watcher/watch/{id}\", map[string]string{\n\t\t\"id\": s.id,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherGetWatchService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherGetWatchService) Do(ctx context.Context) (*XPackWatcherGetWatchResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherGetWatchResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherGetWatchResponse is the response of XPackWatcherGetWatchService.Do.\ntype XPackWatcherGetWatchResponse struct {\n\tFound   bool              `json:\"found\"`\n\tId      string            `json:\"_id\"`\n\tVersion int64             `json:\"_version,omitempty\"`\n\tStatus  *XPackWatchStatus `json:\"status,omitempty\"`\n\tWatch   *XPackWatch       `json:\"watch,omitempty\"`\n}\n\ntype XPackWatchStatus struct {\n\tState            *XPackWatchExecutionState          `json:\"state,omitempty\"`\n\tLastChecked      *time.Time                         `json:\"last_checked,omitempty\"`\n\tLastMetCondition *time.Time                         `json:\"last_met_condition,omitempty\"`\n\tActions          map[string]*XPackWatchActionStatus `json:\"actions,omitempty\"`\n\tExecutionState   string                             `json:\"execution_state,omitempty\"`\n\tHeaders          map[string]string                  `json:\"headers,omitempty\"`\n\tVersion          int64                              `json:\"version\"`\n}\n\ntype XPackWatchExecutionState struct {\n\tActive    bool      `json:\"active\"`\n\tTimestamp time.Time `json:\"timestamp\"`\n}\n\ntype XPackWatchActionStatus struct {\n\tAckStatus               *XPackWatchActionAckStatus      `json:\"ack\"`\n\tLastExecution           *XPackWatchActionExecutionState `json:\"last_execution,omitempty\"`\n\tLastSuccessfulExecution *XPackWatchActionExecutionState `json:\"last_successful_execution,omitempty\"`\n\tLastThrottle            *XPackWatchActionThrottle       `json:\"last_throttle,omitempty\"`\n}\n\ntype XPackWatchActionAckStatus struct {\n\tTimestamp time.Time `json:\"timestamp\"`\n\tState     string    `json:\"state\"`\n}\n\ntype XPackWatchActionExecutionState struct {\n\tTimestamp  time.Time `json:\"timestamp\"`\n\tSuccessful bool      `json:\"successful\"`\n\tReason     string    `json:\"reason,omitempty\"`\n}\n\ntype XPackWatchActionThrottle struct {\n\tTimestamp time.Time `json:\"timestamp\"`\n\tReason    string    `json:\"reason,omitempty\"`\n}\n\ntype XPackWatch struct {\n\tTrigger                map[string]map[string]interface{} `json:\"trigger\"`\n\tInput                  map[string]map[string]interface{} `json:\"input\"`\n\tCondition              map[string]map[string]interface{} `json:\"condition\"`\n\tTransform              map[string]interface{}            `json:\"transform,omitempty\"`\n\tThrottlePeriod         string                            `json:\"throttle_period,omitempty\"`\n\tThrottlePeriodInMillis int64                             `json:\"throttle_period_in_millis,omitempty\"`\n\tActions                map[string]map[string]interface{} `json:\"actions\"`\n\tMetadata               map[string]interface{}            `json:\"metadata,omitempty\"`\n\tStatus                 *XPackWatchStatus                 `json:\"status,omitempty\"`\n}\n"
  },
  {
    "path": "xpack_watcher_get_watch_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/google/go-cmp/cmp\"\n)\n\nfunc TestXPackWatcherGetWatchBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tId        string\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\t\"/_watcher/watch/my-watch\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchGet(test.Id)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunc TestXPackWatchActionStatus_UnmarshalJSON(t *testing.T) {\n\ttests := []struct {\n\t\tInput     []byte\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t[]byte(`\n\t\t\t   {\n\t\t\t     \"ack\" : {\n\t\t\t       \"timestamp\" : \"2019-10-22T15:01:12.163Z\",\n\t\t\t       \"state\" : \"ackable\"\n\t\t\t     },\n\t\t\t     \"last_execution\" : {\n\t\t\t       \"timestamp\" : \"2019-10-22T15:01:12.163Z\",\n\t\t\t       \"successful\" : true\n\t\t\t     },\n\t\t\t     \"last_successful_execution\" : {\n\t\t\t       \"timestamp\" : \"2019-10-22T15:01:12.163Z\",\n\t\t\t       \"successful\" : true\n\t\t\t     }\n\t\t\t   }\n\t\t\t`),\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tvar status XPackWatchActionStatus\n\t\terr := json.Unmarshal(test.Input, &status)\n\t\tif err != nil {\n\t\t\tt.Errorf(\"#%d: expected no error, got %v\", i+1, err)\n\t\t}\n\t\tif status.AckStatus == nil {\n\t\t\tt.Errorf(\"#%d: expected AckStatus!=nil\", i+1)\n\t\t}\n\t\tif status.LastExecution == nil {\n\t\t\tt.Errorf(\"#%d: expected LastExecution!=nil\", i+1)\n\t\t}\n\t\tif status.LastSuccessfulExecution == nil {\n\t\t\tt.Errorf(\"#%d: expected LastSuccessfulExecution!=nil\", i+1)\n\t\t}\n\t}\n}\n\nfunc TestXPackWatchResponseParser(t *testing.T) {\n\tmustParseTime := func(layout, value string) time.Time {\n\t\tdt, err := time.Parse(layout, value)\n\t\tif err != nil {\n\t\t\tt.Fatal(err)\n\t\t}\n\t\treturn dt\n\t}\n\n\ttests := []struct {\n\t\tInput     []byte\n\t\tExpectErr bool\n\t\tResponse  *XPackWatcherGetWatchResponse\n\t}{\n\t\t{\n\t\t\t[]byte(`\n\t\t\t\t{\n\t\t\t\t\t\"found\": true,\n\t\t\t\t\t\"_id\": \"my_watch\",\n\t\t\t\t\t\"_seq_no\": 0,\n\t\t\t\t\t\"_primary_term\": 1,\n\t\t\t\t\t\"_version\": 1,\n\t\t\t\t\t\"status\": { \n\t\t\t\t\t\t\"version\": 1,\n\t\t\t\t\t\t\"state\": {\n\t\t\t\t\t\t\t\"active\": true,\n\t\t\t\t\t\t\t\"timestamp\": \"2015-05-26T18:21:08.630Z\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"actions\": {\n\t\t\t\t\t\t\t\"test_index\": {\n\t\t\t\t\t\t\t\t\"ack\": {\n\t\t\t\t\t\t\t\t\t\"timestamp\": \"2015-05-26T18:21:08.630Z\",\n\t\t\t\t\t\t\t\t\t\"state\": \"awaits_successful_execution\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"watch\": {\n\t\t\t\t\t\t\"input\": {\n\t\t\t\t\t\t\t\"simple\": {\n\t\t\t\t\t\t\t\t\"payload\": {\n\t\t\t\t\t\t\t\t\t\"send\": \"yes\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"condition\": {\n\t\t\t\t\t\t\t\"always\": {}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"trigger\": {\n\t\t\t\t\t\t\t\"schedule\": {\n\t\t\t\t\t\t\t\t\"hourly\": {\n\t\t\t\t\t\t\t\t\t\"minute\": [0, 5]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"actions\": {\n\t\t\t\t\t\t\t\"test_index\": {\n\t\t\t\t\t\t\t\t\"index\": {\n\t\t\t\t\t\t\t\t\t\"index\": \"test\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t`),\n\t\t\tfalse,\n\t\t\t&XPackWatcherGetWatchResponse{\n\t\t\t\tFound:   true,\n\t\t\t\tId:      \"my_watch\",\n\t\t\t\tVersion: 1,\n\t\t\t\tStatus: &XPackWatchStatus{\n\t\t\t\t\tState: &XPackWatchExecutionState{\n\t\t\t\t\t\tActive:    true,\n\t\t\t\t\t\tTimestamp: mustParseTime(time.RFC3339, \"2015-05-26T18:21:08.630Z\"),\n\t\t\t\t\t},\n\t\t\t\t\tActions: map[string]*XPackWatchActionStatus{\n\t\t\t\t\t\t\"test_index\": {\n\t\t\t\t\t\t\tAckStatus: &XPackWatchActionAckStatus{\n\t\t\t\t\t\t\t\tState:     \"awaits_successful_execution\",\n\t\t\t\t\t\t\t\tTimestamp: mustParseTime(time.RFC3339, \"2015-05-26T18:21:08.630Z\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tVersion: 1,\n\t\t\t\t},\n\t\t\t\tWatch: &XPackWatch{\n\t\t\t\t\tTrigger: map[string]map[string]interface{}{\n\t\t\t\t\t\t\"schedule\": {\n\t\t\t\t\t\t\t\"hourly\": map[string]interface{}{\"minute\": []interface{}{float64(0), float64(5)}},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tInput:     map[string]map[string]interface{}{\"simple\": {\"payload\": map[string]interface{}{\"send\": string(\"yes\")}}},\n\t\t\t\t\tCondition: map[string]map[string]interface{}{\"always\": {}},\n\t\t\t\t\tActions:   map[string]map[string]interface{}{\"test_index\": {\"index\": map[string]interface{}{\"index\": string(\"test\")}}},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tvar resp XPackWatcherGetWatchResponse\n\t\terr := json.Unmarshal(test.Input, &resp)\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"#%d: expected no error, got %v\", i+1, err)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif test.ExpectErr {\n\t\t\tt.Errorf(\"#%d: expected error, got none\", i+1)\n\t\t} else {\n\t\t\tif want, have := *test.Response, resp; !cmp.Equal(want, have) {\n\t\t\t\tt.Errorf(\"#%d: diff: %s\\n\", i+1, cmp.Diff(want, have))\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_put_watch.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/olivere/elastic/v7/uritemplates\"\n)\n\n// XPackWatcherPutWatchService either registers a new watch in Watcher\n// or update an existing one.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-put-watch.html.\ntype XPackWatcherPutWatchService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tid            string\n\tactive        *bool\n\tmasterTimeout string\n\tifSeqNo       *int64\n\tifPrimaryTerm *int64\n\tbody          interface{}\n}\n\n// NewXPackWatcherPutWatchService creates a new XPackWatcherPutWatchService.\nfunc NewXPackWatcherPutWatchService(client *Client) *XPackWatcherPutWatchService {\n\treturn &XPackWatcherPutWatchService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherPutWatchService) Pretty(pretty bool) *XPackWatcherPutWatchService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherPutWatchService) Human(human bool) *XPackWatcherPutWatchService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherPutWatchService) ErrorTrace(errorTrace bool) *XPackWatcherPutWatchService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherPutWatchService) FilterPath(filterPath ...string) *XPackWatcherPutWatchService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherPutWatchService) Header(name string, value string) *XPackWatcherPutWatchService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherPutWatchService) Headers(headers http.Header) *XPackWatcherPutWatchService {\n\ts.headers = headers\n\treturn s\n}\n\n// Id of the watch to upsert.\nfunc (s *XPackWatcherPutWatchService) Id(id string) *XPackWatcherPutWatchService {\n\ts.id = id\n\treturn s\n}\n\n// Active specifies whether the watch is in/active by default.\nfunc (s *XPackWatcherPutWatchService) Active(active bool) *XPackWatcherPutWatchService {\n\ts.active = &active\n\treturn s\n}\n\n// MasterTimeout is an explicit operation timeout for connection to master node.\nfunc (s *XPackWatcherPutWatchService) MasterTimeout(masterTimeout string) *XPackWatcherPutWatchService {\n\ts.masterTimeout = masterTimeout\n\treturn s\n}\n\n// IfSeqNo indicates to update the watch only if the last operation that\n// has changed the watch has the specified sequence number.\nfunc (s *XPackWatcherPutWatchService) IfSeqNo(seqNo int64) *XPackWatcherPutWatchService {\n\ts.ifSeqNo = &seqNo\n\treturn s\n}\n\n// IfPrimaryTerm indicates to update the watch only if the last operation that\n// has changed the watch has the specified primary term.\nfunc (s *XPackWatcherPutWatchService) IfPrimaryTerm(primaryTerm int64) *XPackWatcherPutWatchService {\n\ts.ifPrimaryTerm = &primaryTerm\n\treturn s\n}\n\n// Body specifies the watch. Use a string or a type that will get serialized as JSON.\nfunc (s *XPackWatcherPutWatchService) Body(body interface{}) *XPackWatcherPutWatchService {\n\ts.body = body\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherPutWatchService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath, err := uritemplates.Expand(\"/_watcher/watch/{id}\", map[string]string{\n\t\t\"id\": s.id,\n\t})\n\tif err != nil {\n\t\treturn \"\", url.Values{}, err\n\t}\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.active; v != nil {\n\t\tparams.Set(\"active\", fmt.Sprint(*v))\n\t}\n\tif s.masterTimeout != \"\" {\n\t\tparams.Set(\"master_timeout\", s.masterTimeout)\n\t}\n\tif v := s.ifSeqNo; v != nil {\n\t\tparams.Set(\"if_seq_no\", fmt.Sprintf(\"%d\", *v))\n\t}\n\tif v := s.ifPrimaryTerm; v != nil {\n\t\tparams.Set(\"if_primary_term\", fmt.Sprintf(\"%d\", *v))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherPutWatchService) Validate() error {\n\tvar invalid []string\n\tif s.id == \"\" {\n\t\tinvalid = append(invalid, \"Id\")\n\t}\n\tif s.body == nil {\n\t\tinvalid = append(invalid, \"Body\")\n\t}\n\tif len(invalid) > 0 {\n\t\treturn fmt.Errorf(\"missing required fields: %v\", invalid)\n\t}\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherPutWatchService) Do(ctx context.Context) (*XPackWatcherPutWatchResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"PUT\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tBody:    s.body,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherPutWatchResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherPutWatchResponse is the response of XPackWatcherPutWatchService.Do.\ntype XPackWatcherPutWatchResponse struct {\n}\n"
  },
  {
    "path": "xpack_watcher_put_watch_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackWatcherPutWatchBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tId        string\n\t\tBody      interface{}\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\tnil,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"\",\n\t\t\t`{}`,\n\t\t\t\"\",\n\t\t\ttrue,\n\t\t},\n\t\t{\n\t\t\t\"my-watch\",\n\t\t\t`{}`,\n\t\t\t\"/_watcher/watch/my-watch\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchPut(test.Id).Body(test.Body)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_start.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// XPackWatcherStartService starts the watcher service if it is not already running.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-start.html.\ntype XPackWatcherStartService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n}\n\n// NewXPackWatcherStartService creates a new XPackWatcherStartService.\nfunc NewXPackWatcherStartService(client *Client) *XPackWatcherStartService {\n\treturn &XPackWatcherStartService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherStartService) Pretty(pretty bool) *XPackWatcherStartService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherStartService) Human(human bool) *XPackWatcherStartService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherStartService) ErrorTrace(errorTrace bool) *XPackWatcherStartService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherStartService) FilterPath(filterPath ...string) *XPackWatcherStartService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherStartService) Header(name string, value string) *XPackWatcherStartService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherStartService) Headers(headers http.Header) *XPackWatcherStartService {\n\ts.headers = headers\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherStartService) buildURL() (string, url.Values, error) {\n\t// Build URL path\n\tpath := \"/_watcher/_start\"\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherStartService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherStartService) Do(ctx context.Context) (*XPackWatcherStartResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherStartResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherStartResponse is the response of XPackWatcherStartService.Do.\ntype XPackWatcherStartResponse struct {\n\tAcknowledged bool `json:\"acknowledged\"`\n}\n"
  },
  {
    "path": "xpack_watcher_start_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackWatcherStartBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"/_watcher/_start\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchStart()\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_stats.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// XPackWatcherStatsService returns the current watcher metrics.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-stats.html.\ntype XPackWatcherStatsService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n\n\tmetric          string\n\temitStacktraces *bool\n}\n\n// NewXPackWatcherStatsService creates a new XPackWatcherStatsService.\nfunc NewXPackWatcherStatsService(client *Client) *XPackWatcherStatsService {\n\treturn &XPackWatcherStatsService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherStatsService) Pretty(pretty bool) *XPackWatcherStatsService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherStatsService) Human(human bool) *XPackWatcherStatsService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherStatsService) ErrorTrace(errorTrace bool) *XPackWatcherStatsService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherStatsService) FilterPath(filterPath ...string) *XPackWatcherStatsService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherStatsService) Header(name string, value string) *XPackWatcherStatsService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherStatsService) Headers(headers http.Header) *XPackWatcherStatsService {\n\ts.headers = headers\n\treturn s\n}\n\n// Metric controls what additional stat metrics should be include in the response.\nfunc (s *XPackWatcherStatsService) Metric(metric string) *XPackWatcherStatsService {\n\ts.metric = metric\n\treturn s\n}\n\n// EmitStacktraces, if enabled, emits stack traces of currently running watches.\nfunc (s *XPackWatcherStatsService) EmitStacktraces(emitStacktraces bool) *XPackWatcherStatsService {\n\ts.emitStacktraces = &emitStacktraces\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherStatsService) buildURL() (string, url.Values, error) {\n\t// Build URL\n\tpath := \"/_watcher/stats\"\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\tif v := s.emitStacktraces; v != nil {\n\t\tparams.Set(\"emit_stacktraces\", fmt.Sprint(*v))\n\t}\n\tif s.metric != \"\" {\n\t\tparams.Set(\"metric\", s.metric)\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherStatsService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherStatsService) Do(ctx context.Context) (*XPackWatcherStatsResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"GET\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherStatsResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherStatsResponse is the response of XPackWatcherStatsService.Do.\ntype XPackWatcherStatsResponse struct {\n\tStats []XPackWatcherStats `json:\"stats\"`\n}\n\n// XPackWatcherStats represents the stats used in XPackWatcherStatsResponse.\ntype XPackWatcherStats struct {\n\tWatcherState        string                 `json:\"watcher_state\"`\n\tWatchCount          int                    `json:\"watch_count\"`\n\tExecutionThreadPool map[string]interface{} `json:\"execution_thread_pool\"`\n}\n"
  },
  {
    "path": "xpack_watcher_stats_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackWatcherStatsBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tMetric    string\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"\",\n\t\t\t\"/_watcher/stats\",\n\t\t\tfalse,\n\t\t},\n\t\t{\n\t\t\t\"_all\",\n\t\t\t\"/_watcher/stats\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchStats().Metric(test.Metric)\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "xpack_watcher_stop.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// XPackWatcherStopService stops the watcher service if it is running.\n// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/watcher-api-stop.html.\ntype XPackWatcherStopService struct {\n\tclient *Client\n\n\tpretty     *bool       // pretty format the returned JSON response\n\thuman      *bool       // return human readable values for statistics\n\terrorTrace *bool       // include the stack trace of returned errors\n\tfilterPath []string    // list of filters used to reduce the response\n\theaders    http.Header // custom request-level HTTP headers\n}\n\n// NewXPackWatcherStopService creates a new XPackWatcherStopService.\nfunc NewXPackWatcherStopService(client *Client) *XPackWatcherStopService {\n\treturn &XPackWatcherStopService{\n\t\tclient: client,\n\t}\n}\n\n// Pretty tells Elasticsearch whether to return a formatted JSON response.\nfunc (s *XPackWatcherStopService) Pretty(pretty bool) *XPackWatcherStopService {\n\ts.pretty = &pretty\n\treturn s\n}\n\n// Human specifies whether human readable values should be returned in\n// the JSON response, e.g. \"7.5mb\".\nfunc (s *XPackWatcherStopService) Human(human bool) *XPackWatcherStopService {\n\ts.human = &human\n\treturn s\n}\n\n// ErrorTrace specifies whether to include the stack trace of returned errors.\nfunc (s *XPackWatcherStopService) ErrorTrace(errorTrace bool) *XPackWatcherStopService {\n\ts.errorTrace = &errorTrace\n\treturn s\n}\n\n// FilterPath specifies a list of filters used to reduce the response.\nfunc (s *XPackWatcherStopService) FilterPath(filterPath ...string) *XPackWatcherStopService {\n\ts.filterPath = filterPath\n\treturn s\n}\n\n// Header adds a header to the request.\nfunc (s *XPackWatcherStopService) Header(name string, value string) *XPackWatcherStopService {\n\tif s.headers == nil {\n\t\ts.headers = http.Header{}\n\t}\n\ts.headers.Add(name, value)\n\treturn s\n}\n\n// Headers specifies the headers of the request.\nfunc (s *XPackWatcherStopService) Headers(headers http.Header) *XPackWatcherStopService {\n\ts.headers = headers\n\treturn s\n}\n\n// buildURL builds the URL for the operation.\nfunc (s *XPackWatcherStopService) buildURL() (string, url.Values, error) {\n\t// Build URL path\n\tpath := \"/_watcher/_stop\"\n\n\t// Add query string parameters\n\tparams := url.Values{}\n\tif v := s.pretty; v != nil {\n\t\tparams.Set(\"pretty\", fmt.Sprint(*v))\n\t}\n\tif v := s.human; v != nil {\n\t\tparams.Set(\"human\", fmt.Sprint(*v))\n\t}\n\tif v := s.errorTrace; v != nil {\n\t\tparams.Set(\"error_trace\", fmt.Sprint(*v))\n\t}\n\tif len(s.filterPath) > 0 {\n\t\tparams.Set(\"filter_path\", strings.Join(s.filterPath, \",\"))\n\t}\n\treturn path, params, nil\n}\n\n// Validate checks if the operation is valid.\nfunc (s *XPackWatcherStopService) Validate() error {\n\treturn nil\n}\n\n// Do executes the operation.\nfunc (s *XPackWatcherStopService) Do(ctx context.Context) (*XPackWatcherStopResponse, error) {\n\t// Check pre-conditions\n\tif err := s.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get URL for request\n\tpath, params, err := s.buildURL()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Get HTTP response\n\tres, err := s.client.PerformRequest(ctx, PerformRequestOptions{\n\t\tMethod:  \"POST\",\n\t\tPath:    path,\n\t\tParams:  params,\n\t\tHeaders: s.headers,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Return operation response\n\tret := new(XPackWatcherStopResponse)\n\tif err := json.Unmarshal(res.Body, ret); err != nil {\n\t\treturn nil, err\n\t}\n\treturn ret, nil\n}\n\n// XPackWatcherStopResponse is the response of XPackWatcherStopService.Do.\ntype XPackWatcherStopResponse struct {\n\tAcknowledged bool `json:\"acknowledged\"`\n}\n"
  },
  {
    "path": "xpack_watcher_stop_test.go",
    "content": "// Copyright 2012-2018 Oliver Eilhard. All rights reserved.\n// Use of this source code is governed by a MIT-license.\n// See http://olivere.mit-license.org/license.txt for details.\n\npackage elastic\n\nimport (\n\t\"testing\"\n)\n\nfunc TestXPackWatcherStopBuildURL(t *testing.T) {\n\tclient := setupTestClient(t) // , SetURL(\"http://elastic:elastic@localhost:9210\"))\n\n\ttests := []struct {\n\t\tExpected  string\n\t\tExpectErr bool\n\t}{\n\t\t{\n\t\t\t\"/_watcher/_stop\",\n\t\t\tfalse,\n\t\t},\n\t}\n\n\tfor i, test := range tests {\n\t\tbuilder := client.XPackWatchStop()\n\t\terr := builder.Validate()\n\t\tif err != nil {\n\t\t\tif !test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: %v\", i+1, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t} else {\n\t\t\t// err == nil\n\t\t\tif test.ExpectErr {\n\t\t\t\tt.Errorf(\"case #%d: expected error\", i+1)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpath, _, _ := builder.buildURL()\n\t\t\tif path != test.Expected {\n\t\t\t\tt.Errorf(\"case #%d: expected %q; got: %q\", i+1, test.Expected, path)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  }
]